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  }