File: commit_loading_shared.go

package info (click to toggle)
lazygit 0.57.0%2Bds1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 7,748 kB
  • sloc: sh: 153; makefile: 76
file content (74 lines) | stat: -rw-r--r-- 2,333 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package git_commands

import (
	"strings"

	"github.com/jesseduffield/lazygit/pkg/commands/models"
	"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
	"github.com/samber/lo"
)

func loadCommits(
	cmd *oscommands.CmdObj,
	filterPath string,
	parseLogLine func(string) (*models.Commit, bool),
) ([]*models.Commit, error) {
	commits := []*models.Commit{}

	var commit *models.Commit
	var filterPaths []string
	// A string pool that stores interned strings to reduce memory usage
	pool := make(map[string]string)

	finishLastCommit := func() {
		if commit != nil {
			// Only set the filter paths if we have one that is not contained in the original
			// filter path. When filtering on a directory, all file paths will start with that
			// directory, so we needn't bother storing the individual paths. Likewise, if we
			// filter on a file and the file path hasn't changed, we needn't store it either.
			// Only if a file has been moved or renamed do we need to store the paths, but then
			// we need them all so that we can properly render a diff for the rename.
			if lo.SomeBy(filterPaths, func(path string) bool {
				return !strings.HasPrefix(path, filterPath)
			}) {
				commit.FilterPaths = lo.Map(filterPaths, func(path string, _ int) string {
					if v, ok := pool[path]; ok {
						return v
					}
					pool[path] = path
					return path
				})
			}
			commits = append(commits, commit)
			commit = nil
			filterPaths = nil
		}
	}
	err := cmd.RunAndProcessLines(func(line string) (bool, error) {
		if line == "" {
			return false, nil
		}

		if line[0] == '+' {
			finishLastCommit()
			var stop bool
			commit, stop = parseLogLine(line[1:])
			if stop {
				commit = nil
				return true, nil
			}
		} else if commit != nil && filterPath != "" {
			// We are filtering by path, and this line is the output of the --name-status flag
			fields := strings.Split(line, "\t")
			// We don't bother looking at the first field (it will be 'A', 'M', 'R072' or a bunch of others).
			// All we care about is the path(s), and there will be one for 'M' and 'A', and two for 'R' or 'C',
			// in which case we want them both so that we can show the diff between the two.
			if len(fields) > 1 {
				filterPaths = append(filterPaths, fields[1:]...)
			}
		}
		return false, nil
	})
	finishLastCommit()
	return commits, err
}