github.com/fredbi/git-chglog@v0.0.0-20190706071416-d35c598eac81/tag_reader.go (about)

     1  package chglog
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"strings"
     7  	"time"
     8  
     9  	gitcmd "github.com/tsuyoshiwada/go-gitcmd"
    10  )
    11  
    12  type tagReader struct {
    13  	client    gitcmd.Client
    14  	format    string
    15  	separator string
    16  }
    17  
    18  func newTagReader(client gitcmd.Client) *tagReader {
    19  	return &tagReader{
    20  		client:    client,
    21  		separator: "@@__CHGLOG__@@",
    22  	}
    23  }
    24  
    25  func (r *tagReader) ReadAll() ([]*Tag, error) {
    26  	out, err := r.client.Exec(
    27  		"for-each-ref",
    28  		"--format",
    29  		"%(refname)"+r.separator+"%(subject)"+r.separator+"%(taggerdate)"+r.separator+"%(authordate)",
    30  		"refs/tags",
    31  	)
    32  
    33  	tags := []*Tag{}
    34  
    35  	if err != nil {
    36  		return tags, fmt.Errorf("failed to get git-tag: %s", err.Error())
    37  	}
    38  
    39  	lines := strings.Split(out, "\n")
    40  
    41  	for _, line := range lines {
    42  		tokens := strings.Split(line, r.separator)
    43  
    44  		if len(tokens) != 4 {
    45  			continue
    46  		}
    47  
    48  		name := r.parseRefname(tokens[0])
    49  		subject := r.parseSubject(tokens[1])
    50  		date, err := r.parseDate(tokens[2])
    51  		if err != nil {
    52  			t, err2 := r.parseDate(tokens[3])
    53  			if err2 != nil {
    54  				return nil, err2
    55  			}
    56  			date = t
    57  		}
    58  
    59  		tags = append(tags, &Tag{
    60  			Name:    name,
    61  			Subject: subject,
    62  			Date:    date,
    63  		})
    64  	}
    65  
    66  	r.sortTags(tags)
    67  	r.assignPreviousAndNextTag(tags)
    68  
    69  	return tags, nil
    70  }
    71  
    72  func (*tagReader) parseRefname(input string) string {
    73  	return strings.Replace(input, "refs/tags/", "", 1)
    74  }
    75  
    76  func (*tagReader) parseSubject(input string) string {
    77  	return strings.TrimSpace(input)
    78  }
    79  
    80  func (*tagReader) parseDate(input string) (time.Time, error) {
    81  	return time.Parse("Mon Jan 2 15:04:05 2006 -0700", input)
    82  }
    83  
    84  func (*tagReader) assignPreviousAndNextTag(tags []*Tag) {
    85  	total := len(tags)
    86  
    87  	for i, tag := range tags {
    88  		var (
    89  			next *RelateTag
    90  			prev *RelateTag
    91  		)
    92  
    93  		if i > 0 {
    94  			next = &RelateTag{
    95  				Name:    tags[i-1].Name,
    96  				Subject: tags[i-1].Subject,
    97  				Date:    tags[i-1].Date,
    98  			}
    99  		}
   100  
   101  		if i+1 < total {
   102  			prev = &RelateTag{
   103  				Name:    tags[i+1].Name,
   104  				Subject: tags[i+1].Subject,
   105  				Date:    tags[i+1].Date,
   106  			}
   107  		}
   108  
   109  		tag.Next = next
   110  		tag.Previous = prev
   111  	}
   112  }
   113  
   114  func (*tagReader) sortTags(tags []*Tag) {
   115  	sort.Slice(tags, func(i, j int) bool {
   116  		return !tags[i].Date.Before(tags[j].Date)
   117  	})
   118  }