summaryrefslogtreecommitdiffstats
path: root/pkg/commands/models/commit.go
blob: 64b89db8f606c09c4f6fa85519c7f710c3edfe00 (plain)
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package models

import (
	"fmt"

	"github.com/fsmiamoto/git-todo-parser/todo"
	"github.com/jesseduffield/lazygit/pkg/utils"
)

// Special commit hash for empty tree object
const EmptyTreeCommitHash = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"

type CommitStatus int

const (
	StatusNone CommitStatus = iota
	StatusUnpushed
	StatusPushed
	StatusMerged
	StatusRebasing
	StatusSelected
	StatusReflog
)

const (
	// Conveniently for us, the todo package starts the enum at 1, and given
	// that it doesn't have a "none" value, we're setting ours to 0
	ActionNone todo.TodoCommand = 0
	// "Comment" is the last one of the todo package's enum entries
	ActionConflict = todo.Comment + 1
)

type Divergence int

// For a divergence log (left/right comparison of two refs) this is set to
// either DivergenceLeft or DivergenceRight for each commit; for normal
// commit views it is always DivergenceNone.
const (
	DivergenceNone Divergence = iota
	DivergenceLeft
	DivergenceRight
)

// Commit : A git commit
type Commit struct {
	Hash          string
	Name          string
	Status        CommitStatus
	Action        todo.TodoCommand
	Tags          []string
	ExtraInfo     string // something like 'HEAD -> master, tag: v0.15.2'
	AuthorName    string // something like 'Jesse Duffield'
	AuthorEmail   string // something like 'jessedduffield@gmail.com'
	UnixTimestamp int64
	Divergence    Divergence // set to DivergenceNone unless we are showing the divergence view

	// Hashes of parent commits (will be multiple if it's a merge commit)
	Parents []string
}

func (c *Commit) ShortHash() string {
	return utils.ShortHash(c.Hash)
}

func (c *Commit) FullRefName() string {
	return c.Hash
}

func (c *Commit) RefName() string {
	return c.Hash
}

func (c *Commit) ParentRefName() string {
	if c.IsFirstCommit() {
		return EmptyTreeCommitHash
	}
	return c.RefName() + "^"
}

func (c *Commit) IsFirstCommit() bool {
	return len(c.Parents) == 0
}

func (c *Commit) ID() string {
	return c.RefName()
}

func (c *Commit) Description() string {
	return fmt.Sprintf("%s %s", c.Hash[:7], c.Name)
}

func (c *Commit) IsMerge() bool {
	return len(c.Parents) > 1
}

// returns true if this commit is not actually in the git log but instead
// is from a TODO file for an interactive rebase.
func (c *Commit) IsTODO() bool {
	return c.Action != ActionNone
}

func IsHeadCommit(commits []*Commit, index int) bool {
	return !commits[index].IsTODO() && (index == 0 || commits[index-1].IsTODO())
}