Skip to content

Commit b77bbc9

Browse files
authored
Merge pull request go-git#80 from lcostea/master
examples: tag, Add create and push new tag
2 parents 390968c + 884c3a7 commit b77bbc9

File tree

2 files changed

+162
-0
lines changed

2 files changed

+162
-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

+161
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
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+
created, err := setTag(r, tag, defaultSignature(name, email))
34+
if err != nil {
35+
log.Printf("create tag error: %s", err)
36+
return
37+
}
38+
39+
if created {
40+
err = pushTags(r, key)
41+
if err != nil {
42+
log.Printf("push tag error: %s", err)
43+
return
44+
}
45+
}
46+
47+
}
48+
49+
func cloneRepo(url, dir, publicKeyPath string) (*git.Repository, error) {
50+
51+
log.Printf("cloning %s into %s", url, dir)
52+
auth, keyErr := publicKey(publicKeyPath)
53+
if keyErr != nil {
54+
return nil, keyErr
55+
}
56+
57+
Info("git clone %s", url)
58+
r, err := git.PlainClone(dir, false, &git.CloneOptions{
59+
Progress: os.Stdout,
60+
URL: url,
61+
Auth: auth,
62+
})
63+
64+
if err != nil {
65+
log.Printf("clone git repo error: %s", err)
66+
return nil, err
67+
}
68+
69+
return r, nil
70+
}
71+
72+
func publicKey(filePath string) (*ssh.PublicKeys, error) {
73+
var publicKey *ssh.PublicKeys
74+
sshKey, _ := ioutil.ReadFile(filePath)
75+
publicKey, err := ssh.NewPublicKeys("git", []byte(sshKey), "")
76+
if err != nil {
77+
return nil, err
78+
}
79+
return publicKey, err
80+
}
81+
82+
func tagExists(tag string, r *git.Repository) bool {
83+
tagFoundErr := "tag was found"
84+
Info("git show-ref --tag")
85+
tags, err := r.TagObjects()
86+
if err != nil {
87+
log.Printf("get tags error: %s", err)
88+
return false
89+
}
90+
res := false
91+
err = tags.ForEach(func(t *object.Tag) error {
92+
if t.Name == tag {
93+
res = true
94+
return fmt.Errorf(tagFoundErr)
95+
}
96+
return nil
97+
})
98+
if err != nil && err.Error() != tagFoundErr {
99+
log.Printf("iterate tags error: %s", err)
100+
return false
101+
}
102+
return res
103+
}
104+
105+
func setTag(r *git.Repository, tag string, tagger *object.Signature) (bool, error) {
106+
if tagExists(tag, r) {
107+
log.Printf("tag %s already exists", tag)
108+
return false, nil
109+
}
110+
log.Printf("Set tag %s", tag)
111+
h, err := r.Head()
112+
if err != nil {
113+
log.Printf("get HEAD error: %s", err)
114+
return false, err
115+
}
116+
Info("git tag -a %s %s -m \"%s\"", tag, h.Hash(), tag)
117+
_, err = r.CreateTag(tag, h.Hash(), &git.CreateTagOptions{
118+
Tagger: tagger,
119+
Message: tag,
120+
})
121+
122+
if err != nil {
123+
log.Printf("create tag error: %s", err)
124+
return false, err
125+
}
126+
127+
return true, nil
128+
}
129+
130+
func pushTags(r *git.Repository, publicKeyPath string) error {
131+
132+
auth, _ := publicKey(publicKeyPath)
133+
134+
po := &git.PushOptions{
135+
RemoteName: "origin",
136+
Progress: os.Stdout,
137+
RefSpecs: []config.RefSpec{config.RefSpec("refs/tags/*:refs/tags/*")},
138+
Auth: auth,
139+
}
140+
Info("git push --tags")
141+
err := r.Push(po)
142+
143+
if err != nil {
144+
if err == git.NoErrAlreadyUpToDate {
145+
log.Print("origin remote was up to date, no push done")
146+
return nil
147+
}
148+
log.Printf("push to remote origin error: %s", err)
149+
return err
150+
}
151+
152+
return nil
153+
}
154+
155+
func defaultSignature(name, email string) *object.Signature {
156+
return &object.Signature{
157+
Name: name,
158+
Email: email,
159+
When: time.Now(),
160+
}
161+
}

0 commit comments

Comments
 (0)