/
reflog.go
136 lines (117 loc) · 3.03 KB
/
reflog.go
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package store
import (
"bufio"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/JunNishimura/Goit/internal/log"
"github.com/JunNishimura/Goit/internal/sha"
"github.com/fatih/color"
)
type LogRecord struct {
Hash sha.SHA1
Head string
references []string
recType log.RecordType
message string
}
type Reflog struct {
records []*LogRecord
}
func NewReflog(rootGoitPath string, head *Head, refs *Refs) (*Reflog, error) {
reflog := newReflog()
if err := reflog.load(rootGoitPath, head, refs); err != nil {
return nil, err
}
return reflog, nil
}
func newReflog() *Reflog {
return &Reflog{
records: make([]*LogRecord, 0),
}
}
func (r *Reflog) load(rootGoitPath string, head *Head, refs *Refs) error {
headPath := filepath.Join(rootGoitPath, "logs", "HEAD")
f, err := os.Open(headPath)
if err != nil {
return fmt.Errorf("fail to open %s: %w", headPath, err)
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
record := &LogRecord{
references: make([]string, 0),
}
text := scanner.Text()
// extract hash
sp1 := strings.SplitN(text, " ", 3)
if len(sp1) != 3 {
continue
}
if sp1[1] == strings.Repeat("0", 40) {
record.Hash = nil
} else {
hash, err := sha.ReadHash(sp1[1])
if err != nil {
return fmt.Errorf("fail to read hash %s: %w", sp1[1], err)
}
record.Hash = hash
// references
if head.Commit.Hash.Compare(hash) {
record.Head = color.GreenString(head.Reference)
}
branches := refs.getBranchesByHash(hash)
for _, branch := range branches {
record.references = append(record.references, color.GreenString(branch.Name))
}
}
// extract recType
sp2 := strings.Split(sp1[2], "\t")
if len(sp2) != 2 {
continue
}
sp3 := strings.Split(sp2[1], ": ")
if len(sp3) != 2 {
continue
}
recType := log.NewRecordType(sp3[0])
if recType == log.UndefinedRecord {
continue
}
record.recType = recType
record.message = sp3[1]
r.records = append(r.records, record)
}
return nil
}
func (r *Reflog) GetRecord(num int) (*LogRecord, error) {
if num >= len(r.records) {
return nil, fmt.Errorf("num %d needs to be below %d", num, len(r.records)-1)
}
return r.records[len(r.records)-1-num], nil
}
func (r *Reflog) Show() {
for i := range r.records {
idx := len(r.records) - i - 1
record := r.records[idx]
var referenceString string
if len(record.references) > 0 {
var refsExceptHead []string
for _, ref := range record.references {
if ref != record.Head {
refsExceptHead = append(refsExceptHead, ref)
}
}
referenceString = strings.Join(refsExceptHead, ", ")
}
if record.Head != "" {
referenceString = color.BlueString("HEAD -> ") + fmt.Sprintf("%s, ", record.Head) + referenceString
}
if referenceString == "" {
fmt.Printf("%s HEAD@{%d}: %s: %s\n", color.YellowString(record.Hash.String()[:7]), i, record.recType, record.message)
} else {
fmt.Printf("%s (%s) HEAD@{%d}: %s: %s\n", color.YellowString(record.Hash.String()[:7]), referenceString, i, record.recType, record.message)
}
}
}