1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
package main
import (
"fmt"
"log"
"os"
"github.com/go-git/go-git/v5"
. "github.com/go-git/go-git/v5/_examples"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
)
// Example of how create a tag and push it to a remote.
func main() {
CheckArgs("<ssh-url>", "<directory>", "<tag>", "<name>", "<email>", "<public-key>")
url := os.Args[1]
directory := os.Args[2]
tag := os.Args[3]
key := os.Args[6]
r, err := cloneRepo(url, directory, key)
if err != nil {
log.Printf("clone repo error: %s", err)
return
}
created, err := setTag(r, tag)
if err != nil {
log.Printf("create tag error: %s", err)
return
}
if created {
err = pushTags(r, key)
if err != nil {
log.Printf("push tag error: %s", err)
return
}
}
}
func cloneRepo(url, dir, publicKeyPath string) (*git.Repository, error) {
log.Printf("cloning %s into %s", url, dir)
auth, keyErr := publicKey(publicKeyPath)
if keyErr != nil {
return nil, keyErr
}
Info("git clone %s", url)
r, err := git.PlainClone(dir, false, &git.CloneOptions{
Progress: os.Stdout,
URL: url,
Auth: auth,
})
if err != nil {
log.Printf("clone git repo error: %s", err)
return nil, err
}
return r, nil
}
func publicKey(filePath string) (*ssh.PublicKeys, error) {
var publicKey *ssh.PublicKeys
sshKey, _ := os.ReadFile(filePath)
publicKey, err := ssh.NewPublicKeys("git", []byte(sshKey), "")
if err != nil {
return nil, err
}
return publicKey, err
}
func tagExists(tag string, r *git.Repository) bool {
tagFoundErr := "tag was found"
Info("git show-ref --tag")
tags, err := r.TagObjects()
if err != nil {
log.Printf("get tags error: %s", err)
return false
}
res := false
err = tags.ForEach(func(t *object.Tag) error {
if t.Name == tag {
res = true
return fmt.Errorf(tagFoundErr)
}
return nil
})
if err != nil && err.Error() != tagFoundErr {
log.Printf("iterate tags error: %s", err)
return false
}
return res
}
func setTag(r *git.Repository, tag string) (bool, error) {
if tagExists(tag, r) {
log.Printf("tag %s already exists", tag)
return false, nil
}
log.Printf("Set tag %s", tag)
h, err := r.Head()
if err != nil {
log.Printf("get HEAD error: %s", err)
return false, err
}
Info("git tag -a %s %s -m \"%s\"", tag, h.Hash(), tag)
_, err = r.CreateTag(tag, h.Hash(), &git.CreateTagOptions{
Message: tag,
})
if err != nil {
log.Printf("create tag error: %s", err)
return false, err
}
return true, nil
}
func pushTags(r *git.Repository, publicKeyPath string) error {
auth, _ := publicKey(publicKeyPath)
po := &git.PushOptions{
RemoteName: "origin",
Progress: os.Stdout,
RefSpecs: []config.RefSpec{config.RefSpec("refs/tags/*:refs/tags/*")},
Auth: auth,
}
Info("git push --tags")
err := r.Push(po)
if err != nil {
if err == git.NoErrAlreadyUpToDate {
log.Print("origin remote was up to date, no push done")
return nil
}
log.Printf("push to remote origin error: %s", err)
return err
}
return nil
}
|