Skip to content

Commit 9072e77

Browse files
committed
feat: create a separate package for log
moves all utils and log related things into a separate package to be reused by other go packages
1 parent 6c140ac commit 9072e77

File tree

3 files changed

+220
-97
lines changed

3 files changed

+220
-97
lines changed

gitutils.go renamed to log/gitutils.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: MIT
22

3-
package main
3+
package commitlog
44

55
import (
66
"log"

log/log.go

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
package commitlog
4+
5+
import (
6+
"bytes"
7+
"fmt"
8+
"strings"
9+
10+
"github.com/go-git/go-git/v5"
11+
"github.com/go-git/go-git/v5/plumbing/object"
12+
)
13+
14+
// ErrMessage - simple interface around error with a custom message
15+
type ErrMessage struct {
16+
Message string
17+
Err error
18+
}
19+
20+
type commitTypeInclusions [][]byte
21+
22+
// logContainer - Container of log strings
23+
type logContainer struct {
24+
include bool
25+
commits []string
26+
}
27+
28+
// logsByCategory - Type to hold logs by each's category
29+
// to be left as ALLCAPS to be considered as symbols instead of selectors
30+
type logsByCategory struct {
31+
CI logContainer
32+
FIX logContainer
33+
REFACTOR logContainer
34+
FEATURE logContainer
35+
DOCS logContainer
36+
CHORE logContainer
37+
TEST logContainer
38+
OTHER logContainer
39+
UNCLASSIFIED logContainer
40+
}
41+
42+
// Setup - Initialize all Log Containers
43+
func (logs logsByCategory) Setup() {
44+
logs.CI.include = true
45+
logs.FIX.include = true
46+
logs.REFACTOR.include = true
47+
logs.FEATURE.include = true
48+
logs.DOCS.include = true
49+
logs.CHORE.include = true
50+
logs.TEST.include = true
51+
logs.OTHER.include = true
52+
logs.UNCLASSIFIED.include = true
53+
}
54+
55+
// printLog - loops through the collected logs to write them to string builder
56+
func (container logContainer) printLog(out *strings.Builder, title string, skipped bool) {
57+
if !container.include {
58+
return
59+
}
60+
if len(container.commits) > 0 {
61+
if !skipped {
62+
out.WriteString(fmt.Sprintf("\n\n## %s \n", title))
63+
}
64+
for _, item := range container.commits {
65+
out.WriteString(item + "\n")
66+
}
67+
}
68+
}
69+
70+
// ToMarkdown - Generate markdown output for the collected commits
71+
func (logs *logsByCategory) ToMarkdown(skipped bool) string {
72+
var markdownString strings.Builder
73+
74+
markdownString.WriteString("# Changelog \n")
75+
76+
if !skipped {
77+
logs.FEATURE.printLog(&markdownString, "Features", skipped)
78+
logs.FIX.printLog(&markdownString, "Fixes", skipped)
79+
logs.REFACTOR.printLog(&markdownString, "Performance", skipped)
80+
logs.CI.printLog(&markdownString, "CI", skipped)
81+
logs.DOCS.printLog(&markdownString, "Docs", skipped)
82+
logs.CHORE.printLog(&markdownString, "Chores", skipped)
83+
logs.TEST.printLog(&markdownString, "Tests", skipped)
84+
logs.OTHER.printLog(&markdownString, "Other Changes", skipped)
85+
} else {
86+
logs.UNCLASSIFIED.include = true
87+
logs.UNCLASSIFIED.printLog(&markdownString, "Unclassified Changes", skipped)
88+
}
89+
90+
return markdownString.String()
91+
}
92+
93+
// AddCommit - Add a commit to the needed logContainer based on skip and include flag
94+
func (logs *logsByCategory) AddCommit(key, commitHash string, skip bool) {
95+
addCommitToContainer := logs.findContainerByKey(key)
96+
if !addCommitToContainer.canAddToContainer(skip) {
97+
addCommitToContainer = &logs.UNCLASSIFIED
98+
}
99+
if addCommitToContainer != nil {
100+
addCommitToContainer.commits = append(addCommitToContainer.commits, commitHash)
101+
}
102+
}
103+
104+
func (logs *logsByCategory) findContainerByKey(key string) *logContainer {
105+
switch key {
106+
case "ci":
107+
return &logs.CI
108+
case "fix":
109+
return &logs.FIX
110+
case "refactor":
111+
return &logs.REFACTOR
112+
case "feat", "feature":
113+
return &logs.FEATURE
114+
case "docs":
115+
return &logs.DOCS
116+
case "test":
117+
return &logs.TEST
118+
case "chore":
119+
return &logs.CHORE
120+
default:
121+
return &logs.OTHER
122+
}
123+
}
124+
125+
func (container *logContainer) canAddToContainer(skip bool) bool {
126+
if container.include && !skip {
127+
return true
128+
} else if skip && container.include {
129+
return false
130+
}
131+
return true
132+
}
133+
134+
// CommitLog - Generate commit log
135+
func CommitLog(path string, startCommitString string, endCommitString string, inclusionFlags string, skipClassification bool) (string, ErrMessage) {
136+
currentRepository := openRepository(path)
137+
baseCommitReference, err := currentRepository.Head()
138+
var startHash, endHash *object.Commit
139+
var cIter object.CommitIter
140+
141+
if err != nil {
142+
return "", ErrMessage{"Unable to get repository HEAD:", err}
143+
}
144+
145+
if startCommitString != "" {
146+
startHash = GetCommitFromString(startCommitString, currentRepository)
147+
}
148+
149+
if endCommitString != "" {
150+
endHash = GetCommitFromString(endCommitString, currentRepository)
151+
}
152+
153+
if startHash != nil {
154+
cIter, err = currentRepository.Log(&git.LogOptions{From: startHash.Hash})
155+
} else {
156+
cIter, err = currentRepository.Log(&git.LogOptions{From: baseCommitReference.Hash()})
157+
}
158+
159+
if err != nil {
160+
return "", ErrMessage{"Unable to get repository commits:", err}
161+
}
162+
163+
var commits []*object.Commit
164+
165+
err = cIter.ForEach(func(c *object.Commit) error {
166+
commits = append(commits, c)
167+
return nil
168+
})
169+
170+
if err != nil {
171+
return "", ErrMessage{"Error getting commits : ", err}
172+
}
173+
174+
var inclusions commitTypeInclusions = bytes.SplitN([]byte(inclusionFlags), []byte(","), -1)
175+
176+
logContainer := logsByCategory{}
177+
178+
logContainer.Setup()
179+
180+
logContainer.CI.include = inclusions.checkInclusion("ci")
181+
logContainer.FIX.include = inclusions.checkInclusion("fix")
182+
logContainer.REFACTOR.include = inclusions.checkInclusion("refactor")
183+
logContainer.FEATURE.include = inclusions.checkInclusion("feat")
184+
logContainer.DOCS.include = inclusions.checkInclusion("docs")
185+
logContainer.CHORE.include = inclusions.checkInclusion("chore")
186+
logContainer.TEST.include = inclusions.checkInclusion("test")
187+
logContainer.OTHER.include = inclusions.checkInclusion("other")
188+
189+
for _, c := range commits {
190+
normalizedHash := c.Hash.String() + " - " + normalizeCommit(c.Message)
191+
key := strings.SplitN(strings.TrimSpace(c.Message), ":", 2)[0]
192+
193+
logContainer.AddCommit(key, normalizedHash, skipClassification)
194+
195+
if endHash == nil && isCommitToNearestTag(currentRepository, c) {
196+
break
197+
} else if endHash != nil && c.Hash == endHash.Hash {
198+
break
199+
}
200+
}
201+
202+
return logContainer.ToMarkdown(skipClassification), ErrMessage{}
203+
}
204+
205+
func (inclusions *commitTypeInclusions) checkInclusion(flagToCheck string) bool {
206+
if inclusions != nil {
207+
for _, flag := range *inclusions {
208+
if string(flag) == flagToCheck {
209+
return true
210+
}
211+
}
212+
}
213+
return false
214+
}

main.go

Lines changed: 5 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,13 @@
33
package main
44

55
import (
6-
"bytes"
76
"flag"
87
"fmt"
98
"log"
10-
"strings"
119

12-
"github.com/go-git/go-git/v5"
13-
"github.com/go-git/go-git/v5/plumbing/object"
10+
clog "github.com/barelyhuman/commitlog/log"
1411
)
1512

16-
// ErrMessage - simple interface around error with a custom message
17-
type ErrMessage struct {
18-
message string
19-
err error
20-
}
21-
22-
type commitTypeInclusions [][]byte
23-
2413
func main() {
2514
var repoPath = flag.String("p", ".", "path to the repository, points to the current working directory by default")
2615
var startCommit = flag.String("s", "", "commit hash string / revision (ex. HEAD, HEAD^, HEAD~2) \n to start collecting commit messages from")
@@ -30,92 +19,12 @@ func main() {
3019

3120
flag.Parse()
3221

33-
err := CommitLog(*repoPath, *startCommit, *endCommit, *inclusionFlags, *skipClassification)
34-
35-
if err.err != nil {
36-
log.Fatal(err.message, err.err)
37-
}
38-
}
39-
40-
// CommitLog - Generate commit log
41-
func CommitLog(path string, startCommitString string, endCommitString string, inclusionFlags string, skipClassification bool) ErrMessage {
42-
currentRepository := openRepository(path)
43-
baseCommitReference, err := currentRepository.Head()
44-
var startHash, endHash *object.Commit
45-
var cIter object.CommitIter
46-
47-
if err != nil {
48-
return ErrMessage{"Unable to get repository HEAD:", err}
49-
}
50-
51-
if startCommitString != "" {
52-
startHash = GetCommitFromString(startCommitString, currentRepository)
53-
}
54-
55-
if endCommitString != "" {
56-
endHash = GetCommitFromString(endCommitString, currentRepository)
57-
}
58-
59-
if startHash != nil {
60-
cIter, err = currentRepository.Log(&git.LogOptions{From: startHash.Hash})
61-
} else {
62-
cIter, err = currentRepository.Log(&git.LogOptions{From: baseCommitReference.Hash()})
63-
}
22+
changelog, err := clog.CommitLog(*repoPath, *startCommit, *endCommit, *inclusionFlags, *skipClassification)
6423

65-
if err != nil {
66-
return ErrMessage{"Unable to get repository commits:", err}
24+
if err.Err != nil {
25+
log.Fatal(err.Message, err.Err)
6726
}
6827

69-
var commits []*object.Commit
28+
fmt.Println(changelog)
7029

71-
err = cIter.ForEach(func(c *object.Commit) error {
72-
commits = append(commits, c)
73-
return nil
74-
})
75-
76-
if err != nil {
77-
return ErrMessage{"Error getting commits : ", err}
78-
}
79-
80-
var inclusions commitTypeInclusions = bytes.SplitN([]byte(inclusionFlags), []byte(","), -1)
81-
82-
logContainer := logsByCategory{}
83-
84-
logContainer.Setup()
85-
86-
logContainer.CI.include = inclusions.checkInclusion("ci")
87-
logContainer.FIX.include = inclusions.checkInclusion("fix")
88-
logContainer.REFACTOR.include = inclusions.checkInclusion("refactor")
89-
logContainer.FEATURE.include = inclusions.checkInclusion("feat")
90-
logContainer.DOCS.include = inclusions.checkInclusion("docs")
91-
logContainer.CHORE.include = inclusions.checkInclusion("chore")
92-
logContainer.TEST.include = inclusions.checkInclusion("test")
93-
logContainer.OTHER.include = inclusions.checkInclusion("other")
94-
95-
for _, c := range commits {
96-
normalizedHash := c.Hash.String() + " - " + normalizeCommit(c.Message)
97-
key := strings.SplitN(strings.TrimSpace(c.Message), ":", 2)[0]
98-
99-
logContainer.AddCommit(key, normalizedHash, skipClassification)
100-
101-
if endHash == nil && isCommitToNearestTag(currentRepository, c) {
102-
break
103-
} else if endHash != nil && c.Hash == endHash.Hash {
104-
break
105-
}
106-
}
107-
fmt.Println(logContainer.ToMarkdown(skipClassification))
108-
109-
return ErrMessage{}
110-
}
111-
112-
func (inclusions *commitTypeInclusions) checkInclusion(flagToCheck string) bool {
113-
if inclusions != nil {
114-
for _, flag := range *inclusions {
115-
if string(flag) == flagToCheck {
116-
return true
117-
}
118-
}
119-
}
120-
return false
12130
}

0 commit comments

Comments
 (0)