Monorepo for Tangled
at push-xvrvnuvsmslv 99 lines 2.2 kB view raw
1package git 2 3import ( 4 "fmt" 5 "slices" 6 "strconv" 7 "strings" 8 "time" 9 10 "github.com/go-git/go-git/v5/plumbing" 11 "github.com/go-git/go-git/v5/plumbing/object" 12) 13 14func (g *GitRepo) Tags() ([]object.Tag, error) { 15 fields := []string{ 16 "refname:short", 17 "objectname", 18 "objecttype", 19 "*objectname", 20 "*objecttype", 21 "taggername", 22 "taggeremail", 23 "taggerdate:unix", 24 "contents", 25 } 26 27 var outFormat strings.Builder 28 outFormat.WriteString("--format=") 29 for i, f := range fields { 30 if i != 0 { 31 outFormat.WriteString(fieldSeparator) 32 } 33 outFormat.WriteString(fmt.Sprintf("%%(%s)", f)) 34 } 35 outFormat.WriteString("") 36 outFormat.WriteString(recordSeparator) 37 38 output, err := g.forEachRef(outFormat.String(), "refs/tags") 39 if err != nil { 40 return nil, fmt.Errorf("failed to get tags: %w", err) 41 } 42 43 records := strings.Split(strings.TrimSpace(string(output)), recordSeparator) 44 if len(records) == 1 && records[0] == "" { 45 return nil, nil 46 } 47 48 tags := make([]object.Tag, 0, len(records)) 49 50 for _, line := range records { 51 parts := strings.SplitN(strings.TrimSpace(line), fieldSeparator, len(fields)) 52 if len(parts) < 6 { 53 continue 54 } 55 56 tagName := parts[0] 57 objectHash := parts[1] 58 objectType := parts[2] 59 targetHash := parts[3] // dereferenced object hash (empty for lightweight tags) 60 // targetType := parts[4] // dereferenced object type (empty for lightweight tags) 61 taggerName := parts[5] 62 taggerEmail := parts[6] 63 taggerDate := parts[7] 64 message := parts[8] 65 66 // parse creation time 67 var createdAt time.Time 68 if unix, err := strconv.ParseInt(taggerDate, 10, 64); err == nil { 69 createdAt = time.Unix(unix, 0) 70 } 71 72 // parse object type 73 typ, err := plumbing.ParseObjectType(objectType) 74 if err != nil { 75 return nil, err 76 } 77 78 // strip email separators 79 taggerEmail = strings.TrimSuffix(strings.TrimPrefix(taggerEmail, "<"), ">") 80 81 tag := object.Tag{ 82 Hash: plumbing.NewHash(objectHash), 83 Name: tagName, 84 Tagger: object.Signature{ 85 Name: taggerName, 86 Email: taggerEmail, 87 When: createdAt, 88 }, 89 Message: message, 90 TargetType: typ, 91 Target: plumbing.NewHash(targetHash), 92 } 93 94 tags = append(tags, tag) 95 } 96 97 slices.Reverse(tags) 98 return tags, nil 99}