github.com/driusan/dgit@v0.0.0-20221118233547-f39f0c15edbb/git/tag.go (about) 1 package git 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "sort" 8 "strings" 9 "time" 10 ) 11 12 // TagOptions is a stub for when more of Tag is implemented 13 type TagOptions struct { 14 // Replace existing tags instead of erroring out. 15 Force bool 16 17 // Display tags 18 List bool 19 IgnoreCase bool 20 21 Annotated bool 22 23 // Delete the given tag 24 Delete bool 25 } 26 27 // List tags, if tagnames is specified only list tags which match one 28 // of the patterns provided. 29 func TagList(c *Client, opts TagOptions, patterns []string) ([]string, error) { 30 if len(patterns) != 0 { 31 return nil, fmt.Errorf("Tag list with patterns not implemented") 32 } 33 34 files := []string{} 35 36 err := filepath.Walk(filepath.Join(c.GitDir.String(), "refs", "tags"), 37 func(path string, info os.FileInfo, err error) error { 38 if err != nil { 39 return err 40 } 41 if !info.IsDir() { 42 files = append(files, path) 43 } 44 return nil 45 }) 46 if err != nil { 47 return nil, err 48 } 49 50 var tags []string 51 for _, f := range files { 52 tags = append(tags, f[len(c.GitDir.String())+len("/refs/tags/"):]) 53 } 54 sort.Slice(tags, func(i, j int) bool { 55 if opts.IgnoreCase { 56 return strings.ToLower(tags[i]) < strings.ToLower(tags[j]) 57 } 58 return tags[i] < tags[j] 59 }) 60 return tags, nil 61 } 62 63 func TagCommit(c *Client, opts TagOptions, tagname string, cmt Commitish, msg string) error { 64 refspec := RefSpec("refs/tags/" + tagname) 65 var comm CommitID 66 if cmt == nil { 67 cmmt, err := c.GetHeadCommit() 68 if err != nil { 69 return err 70 } 71 comm = cmmt 72 } else { 73 cmmt, err := cmt.CommitID(c) 74 if err != nil { 75 return err 76 } 77 comm = cmmt 78 } 79 if refspec.File(c).Exists() && !opts.Force { 80 return fmt.Errorf("tag '%v' already exists", tagname) 81 } 82 if opts.Annotated { 83 t := time.Now() 84 tagger, err := c.GetCommitter(&t) 85 tagstdin := fmt.Sprintf(`object %v 86 type commit 87 tag %v 88 tagger %v 89 90 %v`, comm, tagname, tagger, msg) 91 tagid, err := Mktag(c, strings.NewReader(tagstdin)) 92 if err != nil { 93 return err 94 } 95 // Pretend it's a CommitID for update-ref's sake. 96 comm = CommitID(tagid) 97 } 98 return UpdateRefSpec(c, UpdateRefOptions{}, refspec, comm, "") 99 } 100 101 func TagDelete(c *Client, opts TagOptions, tagnames []Refname) error { 102 if !opts.Delete { 103 return fmt.Errorf("Must pass Delete option") 104 } 105 106 if len(tagnames) == 0 { 107 return fmt.Errorf("No tags provided to delete") 108 } 109 // Convert the given tags to the full ref name 110 var tagpatterns []string 111 for _, tag := range tagnames { 112 tagpatterns = append(tagpatterns, tag.String()) 113 } 114 tags, err := ShowRef(c, ShowRefOptions{Tags: true}, tagpatterns) 115 if err != nil { 116 return err 117 } 118 if len(tags) == 0 { 119 return fmt.Errorf("No matching tags found") 120 } 121 for _, tag := range tags { 122 if !strings.HasPrefix(tag.Name, "refs/tags") { 123 return fmt.Errorf("Invalid tag: %v", tag.Name) 124 } 125 file := c.GitDir.File(File(tag.Name)) 126 if err := os.Remove(file.String()); err != nil { 127 return err 128 } 129 } 130 return nil 131 }