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(&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) {
    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  }