Skip to content

Commit ba94982

Browse files
committed
examples: tag, Add create and push new tag
1 parent 8019144 commit ba94982

File tree

2 files changed

+169
-0
lines changed

2 files changed

+169
-0
lines changed

_examples/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Here you can find a list of annotated _go-git_ examples:
1717
- [log](log/main.go) - Emulate `git log` command output iterating all the commit history from HEAD reference.
1818
- [branch](branch/main.go) - How to create and remove branches or any other kind of reference.
1919
- [tag](tag/main.go) - List/print repository tags.
20+
- [tag create and push](tag-create-push/main.go) - Create and push a new tag.
2021
- [remotes](remotes/main.go) - Working with remotes: adding, removing, etc.
2122
- [progress](progress/main.go) - Printing the progress information from the sideband.
2223
- [revision](revision/main.go) - Solve a revision into a commit.

_examples/tag-create-push/main.go

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

0 commit comments

Comments
 (0)