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 }