Skip to content

Commit 2529f7a

Browse files
committed
update branch compare api and test suite
1 parent 7bad400 commit 2529f7a

11 files changed

+317
-118
lines changed

controller/branch_controller.go

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package controller
22

33
import (
4-
"errors"
54
git2go "github.com/libgit2/git2go/v31"
65
"github.com/neel1996/gitconvex/git/branch"
76
"github.com/neel1996/gitconvex/git/branch/checkout"
@@ -14,7 +13,7 @@ type BranchController interface {
1413
GitAddBranch(branchName string, isRemoteBranch bool, targetCommit *git2go.Commit) (string, error)
1514
GitCheckoutBranch(branchName string) (string, error)
1615
GitDeleteBranch(branchName string) (*model.BranchDeleteStatus, error)
17-
GitCompareBranches() ([]*model.BranchCompareResults, error)
16+
GitCompareBranches(baseBranch string, compareBranch string) ([]*model.BranchCompareResults, error)
1817
GitListBranches() (model.ListOfBranches, error)
1918
}
2019

@@ -46,14 +45,8 @@ func (b branchController) GitCheckoutBranch(branchName string) (string, error) {
4645
return global.BranchCheckoutSuccess, nil
4746
}
4847

49-
func (b branchController) GitCompareBranches() ([]*model.BranchCompareResults, error) {
50-
branchDiff := b.compare.CompareBranch()
51-
52-
if len(branchDiff) == 0 {
53-
return []*model.BranchCompareResults{}, errors.New("no difference between the two branches")
54-
}
55-
56-
return branchDiff, nil
48+
func (b branchController) GitCompareBranches(baseBranch string, compareBranch string) ([]*model.BranchCompareResults, error) {
49+
return b.compare.CompareBranch(baseBranch, compareBranch)
5750
}
5851

5952
func (b branchController) GitDeleteBranch(branchName string) (*model.BranchDeleteStatus, error) {

git/branch/errors.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ type Error struct {
99
var (
1010
NilRepoError = Error{ErrorCode: "REPO_NIL_ERROR", ErrorString: "Repo is nil"}
1111
EmptyBranchNameError = Error{ErrorCode: "BRANCH_EMPTY_ERROR", ErrorString: "Branch name(s) is empty"}
12+
LookupError = Error{ErrorCode: "BRANCH_LOOKUP_ERROR", ErrorString: "Branch lookup Failed"}
13+
CompareError = Error{ErrorCode: "BRANCH_COMPARE_ERROR", ErrorString: "Comparing the two branches returned no difference"}
14+
NilHeadError = Error{ErrorCode: "REPO_HEAD_ERROR", ErrorString: "Can not fetch repo HEAD"}
1215
)
1316

1417
func (e Error) Error() string {

git/branch/git_branch_compare.go

Lines changed: 89 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -3,78 +3,116 @@ package branch
33
import (
44
"fmt"
55
git2go "github.com/libgit2/git2go/v31"
6+
"github.com/neel1996/gitconvex/git/middleware"
67
"github.com/neel1996/gitconvex/global"
78
"github.com/neel1996/gitconvex/graph/model"
9+
"github.com/neel1996/gitconvex/validator"
810
"sort"
911
"strings"
1012
)
1113

1214
type Compare interface {
13-
CompareBranch() []*model.BranchCompareResults
15+
CompareBranch(baseBranchName string, diffBranchName string) ([]*model.BranchCompareResults, error)
1416
}
1517

1618
type branchCompare struct {
17-
repo *git2go.Repository
18-
baseBranch string
19-
diffBranch string
19+
repo middleware.Repository
20+
branchValidator validator.ValidatorWithStringFields
2021
}
2122

22-
func returnBranchCompareError(errString string) []*model.BranchCompareResults {
23-
if errString != "" {
24-
logger.Log(errString, global.StatusWarning)
25-
return []*model.BranchCompareResults{}
26-
}
27-
return nil
23+
func logAndReturnError(err error) ([]*model.BranchCompareResults, error) {
24+
logger.Log(err.Error(), global.StatusError)
25+
return []*model.BranchCompareResults{}, err
2826
}
2927

3028
// CompareBranch compares two branches and returns the commits which are different from each other
3129
// The function uses the git client to fetch the results as go-git lacks this feature
32-
func (b branchCompare) CompareBranch() []*model.BranchCompareResults {
30+
func (b branchCompare) CompareBranch(baseBranchName string, diffBranchName string) ([]*model.BranchCompareResults, error) {
3331
var diffCommits []*model.BranchCompareResults
3432
var filteredCommits []model.GitCommits
35-
repo := b.repo
3633

37-
if err := NewBranchFieldsValidation(repo, b.baseBranch, b.diffBranch).ValidateBranchFields(); err != nil {
38-
return returnBranchCompareError(err.Error())
34+
if validationErr := b.branchValidator.ValidateWithFields(baseBranchName, diffBranchName); validationErr != nil {
35+
return logAndReturnError(validationErr)
3936
}
4037

41-
baseBranch, baseBranchErr := repo.LookupBranch(b.baseBranch, git2go.BranchLocal)
42-
compareBranch, compareBranchErr := repo.LookupBranch(b.diffBranch, git2go.BranchLocal)
43-
44-
if baseBranchErr != nil || compareBranchErr != nil {
45-
return returnBranchCompareError(fmt.Sprintf("Unable to lookup target branches from the repo : %v %v", baseBranchErr, compareBranchErr))
38+
baseBranch, compareBranch, lookupErr := b.lookupBranch(baseBranchName, diffBranchName)
39+
if lookupErr != nil {
40+
return logAndReturnError(LookupError)
4641
}
4742

48-
compareResult := baseBranch.Cmp(compareBranch.Reference)
43+
compareResult := baseBranch.Cmp(compareBranch.Reference())
4944
if compareResult == 0 {
50-
return returnBranchCompareError("There are no difference between both the branches")
45+
return logAndReturnError(CompareError)
5146
}
5247

53-
baseTarget := baseBranch.Target()
54-
compareTarget := compareBranch.Target()
48+
baseHeadCommit, compareHeadCommit, headCommitErr := b.getHeadCommits(baseBranch, compareBranch)
49+
if headCommitErr != nil {
50+
return logAndReturnError(NilHeadError)
51+
}
52+
53+
baseBranchCommits, compareBranchCommits := b.getAncestorsOf(baseHeadCommit, compareHeadCommit)
5554

56-
baseHead, _ := repo.LookupCommit(baseTarget)
57-
compareHead, _ := repo.LookupCommit(compareTarget)
55+
filteredCommits = filterDifferingCommits(compareBranchCommits, baseBranchCommits)
56+
commitMap := generateCommitMap(filteredCommits)
57+
diffCommits = sortCommitsInDescendingOrderOfDate(commitMap, diffCommits)
5858

59-
if baseHead == nil || compareHead == nil {
60-
return returnBranchCompareError("Branch head is NIL")
59+
return diffCommits, nil
60+
}
61+
62+
func (b branchCompare) lookupBranch(baseBranchName string, diffBranchName string) (middleware.Branch, middleware.Branch, error) {
63+
var (
64+
baseBranchErr error
65+
compareBranchErr error
66+
)
67+
68+
baseBranch, baseBranchErr := b.repo.LookupBranch(baseBranchName, git2go.BranchLocal)
69+
70+
if baseBranchErr != nil {
71+
logger.Log(baseBranchErr.Error(), global.StatusError)
72+
return nil, nil, baseBranchErr
6173
}
6274

63-
baseBranchMap := make(map[string]*git2go.Commit)
64-
compareBranchMap := make(map[string]*git2go.Commit)
75+
compareBranch, compareBranchErr := b.repo.LookupBranch(diffBranchName, git2go.BranchLocal)
76+
if compareBranchErr != nil {
77+
logger.Log(compareBranchErr.Error(), global.StatusError)
78+
return nil, nil, compareBranchErr
79+
}
6580

66-
baseBranchMap = getParentCommits(baseHead)
67-
compareBranchMap = getParentCommits(compareHead)
81+
return baseBranch, compareBranch, nil
82+
}
6883

69-
filteredCommits = filterDifferingCommits(compareBranchMap, baseBranchMap)
70-
commitMap := generateCommitMaps(filteredCommits)
71-
diffCommits = sortCommitsBasedOnDate(commitMap, diffCommits)
84+
func (b branchCompare) getHeadCommits(baseBranch middleware.Branch, compareBranch middleware.Branch) (middleware.Commit, middleware.Commit, error) {
85+
var (
86+
baseHeadErr error
87+
compareHeadErr error
88+
)
7289

73-
return diffCommits
90+
baseTarget := baseBranch.Target()
91+
baseHead, baseHeadErr := b.repo.LookupCommitV2(baseTarget)
92+
if baseHeadErr != nil {
93+
logger.Log(baseHeadErr.Error(), global.StatusError)
94+
return nil, nil, baseHeadErr
95+
}
96+
97+
compareTarget := compareBranch.Target()
98+
compareHead, compareHeadErr := b.repo.LookupCommitV2(compareTarget)
99+
if compareHeadErr != nil {
100+
logger.Log(compareHeadErr.Error(), global.StatusError)
101+
return nil, nil, compareHeadErr
102+
}
103+
104+
return baseHead, compareHead, nil
105+
}
106+
107+
func (b branchCompare) getAncestorsOf(baseHead middleware.Commit, compareHead middleware.Commit) (map[string]middleware.Commit, map[string]middleware.Commit) {
108+
baseBranchMap := getParentCommitsOf(baseHead)
109+
compareBranchMap := getParentCommitsOf(compareHead)
110+
111+
return baseBranchMap, compareBranchMap
74112
}
75113

76114
// Organizing differing commits based on date
77-
func generateCommitMaps(filteredCommits []model.GitCommits) map[string][]*model.GitCommits {
115+
func generateCommitMap(filteredCommits []model.GitCommits) map[string][]*model.GitCommits {
78116
var commitMap = make(map[string][]*model.GitCommits)
79117
var commitHashMap = make(map[string]bool)
80118

@@ -83,7 +121,7 @@ func generateCommitMaps(filteredCommits []model.GitCommits) map[string][]*model.
83121

84122
j := i
85123
for j < len(filteredCommits) {
86-
if shouldBreakLoop(selectedDate, filteredCommits, j, commitHashMap) {
124+
if isCommitDateNotTheSelectedDate(selectedDate, filteredCommits, j) && isCommitHashAlreadyInTheList(commitHashMap, filteredCommits, j) {
87125
break
88126
}
89127

@@ -103,19 +141,23 @@ func generateCommitMaps(filteredCommits []model.GitCommits) map[string][]*model.
103141
return commitMap
104142
}
105143

106-
func shouldBreakLoop(selectedDate string, filteredCommits []model.GitCommits, iterator int, commitHashMap map[string]bool) bool {
144+
func isCommitDateNotTheSelectedDate(selectedDate string, filteredCommits []model.GitCommits, iterator int) bool {
107145
if selectedDate != *filteredCommits[iterator].CommitTime {
108146
return true
109147
}
110148

149+
return false
150+
}
151+
152+
func isCommitHashAlreadyInTheList(commitHashMap map[string]bool, filteredCommits []model.GitCommits, iterator int) bool {
111153
if len(commitHashMap) > 0 && commitHashMap[*filteredCommits[iterator].Hash] {
112154
return true
113155
}
114156

115157
return false
116158
}
117159

118-
func filterDifferingCommits(compareBranchMap map[string]*git2go.Commit, baseBranchMap map[string]*git2go.Commit) []model.GitCommits {
160+
func filterDifferingCommits(compareBranchMap map[string]middleware.Commit, baseBranchMap map[string]middleware.Commit) []model.GitCommits {
119161
var commits []model.GitCommits
120162
for commitHash, commit := range compareBranchMap {
121163
if baseBranchMap[commitHash] == nil {
@@ -135,33 +177,32 @@ func filterDifferingCommits(compareBranchMap map[string]*git2go.Commit, baseBran
135177
return commits
136178
}
137179

138-
func getParentCommits(head *git2go.Commit) map[string]*git2go.Commit {
139-
var next *git2go.Commit
140-
commitMap := make(map[string]*git2go.Commit)
180+
func getParentCommitsOf(head middleware.Commit) map[string]middleware.Commit {
181+
var next middleware.Commit
182+
commitMap := make(map[string]middleware.Commit)
141183

142184
if head.ParentCount() == 0 {
143185
return commitMap
144186
}
145187

146188
next = head.Parent(0)
147189
for next != nil {
190+
fmt.Println("Next : ", next)
148191
commitMap[next.Id().String()] = next
149192
next = next.Parent(0)
150193
}
151194

152195
return commitMap
153196
}
154197

155-
func sortCommitsBasedOnDate(commitMap map[string][]*model.GitCommits, diffCommits []*model.BranchCompareResults) []*model.BranchCompareResults {
156-
// Sorting commits in reverse chronological order of date
198+
func sortCommitsInDescendingOrderOfDate(commitMap map[string][]*model.GitCommits, diffCommits []*model.BranchCompareResults) []*model.BranchCompareResults {
157199
var keys []string
158200
for k := range commitMap {
159201
keys = append(keys, k)
160202
}
161203
sort.Strings(keys)
162204
sort.Sort(sort.Reverse(sort.StringSlice(keys)))
163205

164-
// Extracting differing commits to the resultant model
165206
for _, date := range keys {
166207
diffCommits = append(diffCommits, &model.BranchCompareResults{
167208
Date: date,
@@ -171,10 +212,9 @@ func sortCommitsBasedOnDate(commitMap map[string][]*model.GitCommits, diffCommit
171212
return diffCommits
172213
}
173214

174-
func NewBranchCompare(repo *git2go.Repository, baseBranch string, diffBranch string) Compare {
215+
func NewBranchCompare(repo middleware.Repository, branchValidator validator.ValidatorWithStringFields) Compare {
175216
return branchCompare{
176-
repo: repo,
177-
baseBranch: baseBranch,
178-
diffBranch: diffBranch,
217+
repo: repo,
218+
branchValidator: branchValidator,
179219
}
180220
}

0 commit comments

Comments
 (0)