github.com/fredbi/git-chglog@v0.0.0-20190706071416-d35c598eac81/commit_extractor.go (about) 1 package chglog 2 3 import ( 4 "sort" 5 "strings" 6 ) 7 8 type commitExtractor struct { 9 opts *Options 10 } 11 12 func newCommitExtractor(opts *Options) *commitExtractor { 13 return &commitExtractor{ 14 opts: opts, 15 } 16 } 17 18 func (e *commitExtractor) Extract(commits []*Commit) ([]*CommitGroup, []*Commit, []*Commit, []*NoteGroup) { 19 commitGroups := []*CommitGroup{} 20 noteGroups := []*NoteGroup{} 21 mergeCommits := []*Commit{} 22 revertCommits := []*Commit{} 23 24 filteredCommits := commitFilter(commits, e.opts.CommitFilters) 25 26 for _, commit := range commits { 27 if commit.Merge != nil { 28 mergeCommits = append(mergeCommits, commit) 29 continue 30 } 31 32 if commit.Revert != nil { 33 revertCommits = append(revertCommits, commit) 34 continue 35 } 36 } 37 38 for _, commit := range filteredCommits { 39 if commit.Merge == nil && commit.Revert == nil { 40 e.processCommitGroups(&commitGroups, commit) 41 } 42 43 e.processNoteGroups(¬eGroups, commit) 44 } 45 46 e.sortCommitGroups(commitGroups) 47 e.sortNoteGroups(noteGroups) 48 49 return commitGroups, mergeCommits, revertCommits, noteGroups 50 } 51 52 func (e *commitExtractor) processCommitGroups(groups *[]*CommitGroup, commit *Commit) { 53 var group *CommitGroup 54 55 // commit group 56 raw, ttl := e.commitGroupTitle(commit) 57 58 for _, g := range *groups { 59 if g.RawTitle == raw { 60 group = g 61 } 62 } 63 64 if group != nil { 65 group.Commits = append(group.Commits, commit) 66 } else if raw != "" { 67 *groups = append(*groups, &CommitGroup{ 68 RawTitle: raw, 69 Title: ttl, 70 Commits: []*Commit{commit}, 71 }) 72 } 73 } 74 75 func (e *commitExtractor) processNoteGroups(groups *[]*NoteGroup, commit *Commit) { 76 if len(commit.Notes) != 0 { 77 for _, note := range commit.Notes { 78 e.appendNoteToNoteGroups(groups, note) 79 } 80 } 81 } 82 83 func (e *commitExtractor) appendNoteToNoteGroups(groups *[]*NoteGroup, note *Note) { 84 exist := false 85 86 for _, g := range *groups { 87 if g.Title == note.Title { 88 exist = true 89 g.Notes = append(g.Notes, note) 90 } 91 } 92 93 if !exist { 94 *groups = append(*groups, &NoteGroup{ 95 Title: note.Title, 96 Notes: []*Note{note}, 97 }) 98 } 99 } 100 101 func (e *commitExtractor) commitGroupTitle(commit *Commit) (string, string) { 102 var ( 103 raw string 104 ttl string 105 ) 106 107 if title, ok := dotGet(commit, e.opts.CommitGroupBy); ok { 108 if v, ok := title.(string); ok { 109 raw = v 110 if t, ok := e.opts.CommitGroupTitleMaps[v]; ok { 111 ttl = t 112 } else { 113 ttl = strings.Title(raw) 114 } 115 } 116 } 117 118 return raw, ttl 119 } 120 121 func (e *commitExtractor) sortCommitGroups(groups []*CommitGroup) { 122 // groups 123 sort.Slice(groups, func(i, j int) bool { 124 var ( 125 a, b interface{} 126 ok bool 127 ) 128 129 a, ok = dotGet(groups[i], e.opts.CommitGroupSortBy) 130 if !ok { 131 return false 132 } 133 134 b, ok = dotGet(groups[j], e.opts.CommitGroupSortBy) 135 if !ok { 136 return false 137 } 138 139 res, err := compare(a, "<", b) 140 if err != nil { 141 return false 142 } 143 return res 144 }) 145 146 // commits 147 for _, group := range groups { 148 sort.Slice(group.Commits, func(i, j int) bool { 149 var ( 150 a, b interface{} 151 ok bool 152 ) 153 154 a, ok = dotGet(group.Commits[i], e.opts.CommitSortBy) 155 if !ok { 156 return false 157 } 158 159 b, ok = dotGet(group.Commits[j], e.opts.CommitSortBy) 160 if !ok { 161 return false 162 } 163 164 res, err := compare(a, "<", b) 165 if err != nil { 166 return false 167 } 168 return res 169 }) 170 } 171 } 172 173 func (e *commitExtractor) sortNoteGroups(groups []*NoteGroup) { 174 // groups 175 sort.Slice(groups, func(i, j int) bool { 176 return strings.ToLower(groups[i].Title) < strings.ToLower(groups[j].Title) 177 }) 178 179 // notes 180 for _, group := range groups { 181 sort.Slice(group.Notes, func(i, j int) bool { 182 return strings.ToLower(group.Notes[i].Title) < strings.ToLower(group.Notes[j].Title) 183 }) 184 } 185 }