github.com/brandonmanuel/git-chglog@v0.0.0-20200903004639-7a62fa08787a/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, e.opts.NoCaseSensitive)
    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, e.opts.NoCaseSensitive)
    41  		}
    42  
    43  		e.processNoteGroups(&noteGroups, 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, noCaseSensitive bool) {
    53  	var group *CommitGroup
    54  
    55  	// commit group
    56  	raw, ttl := e.commitGroupTitle(commit)
    57  
    58  	for _, g := range *groups {
    59  		rawTitleTmp := g.RawTitle
    60  		if noCaseSensitive {
    61  			rawTitleTmp = strings.ToLower(g.RawTitle)
    62  		}
    63  
    64  		rawTmp := raw
    65  		if noCaseSensitive {
    66  			rawTmp = strings.ToLower(raw)
    67  		}
    68  		if rawTitleTmp == rawTmp {
    69  			group = g
    70  		}
    71  	}
    72  
    73  	if group != nil {
    74  		group.Commits = append(group.Commits, commit)
    75  	} else if raw != "" {
    76  		*groups = append(*groups, &CommitGroup{
    77  			RawTitle: raw,
    78  			Title:    ttl,
    79  			Commits:  []*Commit{commit},
    80  		})
    81  	}
    82  }
    83  
    84  func (e *commitExtractor) processNoteGroups(groups *[]*NoteGroup, commit *Commit) {
    85  	if len(commit.Notes) != 0 {
    86  		for _, note := range commit.Notes {
    87  			e.appendNoteToNoteGroups(groups, note)
    88  		}
    89  	}
    90  }
    91  
    92  func (e *commitExtractor) appendNoteToNoteGroups(groups *[]*NoteGroup, note *Note) {
    93  	exist := false
    94  
    95  	for _, g := range *groups {
    96  		if g.Title == note.Title {
    97  			exist = true
    98  			g.Notes = append(g.Notes, note)
    99  		}
   100  	}
   101  
   102  	if !exist {
   103  		*groups = append(*groups, &NoteGroup{
   104  			Title: note.Title,
   105  			Notes: []*Note{note},
   106  		})
   107  	}
   108  }
   109  
   110  func (e *commitExtractor) commitGroupTitle(commit *Commit) (string, string) {
   111  	var (
   112  		raw string
   113  		ttl string
   114  	)
   115  
   116  	if title, ok := dotGet(commit, e.opts.CommitGroupBy); ok {
   117  		if v, ok := title.(string); ok {
   118  			raw = v
   119  			if t, ok := e.opts.CommitGroupTitleMaps[v]; ok {
   120  				ttl = t
   121  			} else {
   122  				ttl = strings.Title(raw)
   123  			}
   124  		}
   125  	}
   126  
   127  	return raw, ttl
   128  }
   129  
   130  func (e *commitExtractor) sortCommitGroups(groups []*CommitGroup) {
   131  	// groups
   132  	sort.Slice(groups, func(i, j int) bool {
   133  		var (
   134  			a, b interface{}
   135  			ok   bool
   136  		)
   137  
   138  		a, ok = dotGet(groups[i], e.opts.CommitGroupSortBy)
   139  		if !ok {
   140  			return false
   141  		}
   142  
   143  		b, ok = dotGet(groups[j], e.opts.CommitGroupSortBy)
   144  		if !ok {
   145  			return false
   146  		}
   147  
   148  		res, err := compare(a, "<", b)
   149  		if err != nil {
   150  			return false
   151  		}
   152  		return res
   153  	})
   154  
   155  	// commits
   156  	for _, group := range groups {
   157  		sort.Slice(group.Commits, func(i, j int) bool {
   158  			var (
   159  				a, b interface{}
   160  				ok   bool
   161  			)
   162  
   163  			a, ok = dotGet(group.Commits[i], e.opts.CommitSortBy)
   164  			if !ok {
   165  				return false
   166  			}
   167  
   168  			b, ok = dotGet(group.Commits[j], e.opts.CommitSortBy)
   169  			if !ok {
   170  				return false
   171  			}
   172  
   173  			res, err := compare(a, "<", b)
   174  			if err != nil {
   175  				return false
   176  			}
   177  			return res
   178  		})
   179  	}
   180  }
   181  
   182  func (e *commitExtractor) sortNoteGroups(groups []*NoteGroup) {
   183  	// groups
   184  	sort.Slice(groups, func(i, j int) bool {
   185  		return strings.ToLower(groups[i].Title) < strings.ToLower(groups[j].Title)
   186  	})
   187  
   188  	// notes
   189  	for _, group := range groups {
   190  		sort.Slice(group.Notes, func(i, j int) bool {
   191  			return strings.ToLower(group.Notes[i].Title) < strings.ToLower(group.Notes[j].Title)
   192  		})
   193  	}
   194  }