Skip to content

Commit 1106f8f

Browse files
author
Adam Kunicki
committed
Switch to go-git for a pure golang implementation
After src-d/go-git#1081 was merged, the performance seems to be significantly better (usable). Even if a slight bit slower, this means theres no more CGO dependency making it much more portable.
1 parent 8a2b0a1 commit 1106f8f

File tree

8 files changed

+169
-149
lines changed

8 files changed

+169
-149
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,7 @@ beer
1919

2020
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
2121
.glide/
22+
vendor/
23+
24+
# ignore release binaries
25+
dist/

.gitlab-ci.yml

Lines changed: 10 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,16 @@
1-
image: golang:1.11
2-
3-
variables:
4-
GOFLAGS: -mod=readonly
5-
GOPATH: ${CI_PROJECT_DIR}/vendor/go
6-
PKG_CONFIG_PATH: ${CI_PROJECT_DIR}/libgit2/lib/pkgconfig
7-
8-
.modcache: &modcache
9-
key: modcache
10-
paths:
11-
- vendor/go/pkg/mod/
12-
- libgit2
13-
14-
before_script:
15-
- apt-get -qq update
16-
- apt-get install -y libssh2-1-dev cmake libssl-dev zlib1g-dev libcurl4-openssl-dev
1+
image: docker:stable
2+
services:
3+
- docker:dind
174

185
stages:
19-
- dependencies
20-
- test
21-
- build
6+
- build
227

23-
dependencies:
24-
stage: dependencies
25-
before_script:
26-
- apt-get -qq update
27-
- apt-get install -y libssh2-1-dev cmake libssl-dev zlib1g-dev libcurl4-openssl-dev
28-
- wget https://github.com/libgit2/libgit2/archive/v0.27.8.tar.gz
29-
- tar xf v0.27.8.tar.gz
30-
- mkdir -p ${CI_PROJECT_DIR}/libgit2
31-
- pushd libgit2-0.27.8 && mkdir -p build && cd build && cmake .. -DCMAKE_INSTALL_PREFIX=${CI_PROJECT_DIR}/libgit2 && cmake --build . --target install && popd
32-
33-
script: go mod download
34-
cache: *modcache
35-
36-
test:
37-
stage: test
38-
image: golang:1.11
39-
cache:
40-
<<: *modcache
41-
policy: pull
42-
script: go test ./...
8+
variables:
9+
GORELEASER_IMAGE: goreleaser/goreleaser:latest
10+
DOCKER_REGISTRY: https://index.docker.io/v1/
4311

4412
build:
4513
stage: build
46-
cache:
47-
<<: *modcache
48-
policy: pull
49-
script: go build
50-
artifacts:
51-
paths:
52-
- beer
53-
expire_in: 1 week
54-
14+
script:
15+
- docker pull $GORELEASER_IMAGE
16+
- docker run --rm --privileged -v $PWD:/go/src/github.com/kunickiaj/beer -v /var/run/docker.sock:/var/run/docker.sock -w /go/src/github.com/kunickiaj/beer -e GITHUB_TOKEN -e DOCKER_USERNAME -e DOCKER_PASSWORD -e DOCKER_REGISTRY $GORELEASER_IMAGE release --rm-dist

.goreleaser.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
before:
2+
hooks:
3+
builds:
4+
- env:
5+
- CGO_ENABLED=0
6+
archives:
7+
- id: dist
8+
replacements:
9+
darwin: Darwin
10+
linux: Linux
11+
windows: Windows
12+
amd64: x86_64
13+
dockers:
14+
-
15+
goos: linux
16+
goarch: amd64
17+
binaries:
18+
- beer
19+
image_templates:
20+
- 'kunickiaj/beer:{{ .Tag }}'
21+
- 'kunickiaj/beer:latest'
22+
checksum:
23+
name_template: 'checksums.txt'
24+
snapshot:
25+
name_template: "{{ .Tag }}-next"
26+
changelog:
27+
sort: asc
28+
filters:
29+
exclude:
30+
- '^docs:'
31+
- '^test:'

Dockerfile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
FROM scratch
2+
3+
ADD beer /beer
4+
5+
ENTRYPOINT [ "/beer" ]
6+
CMD [ "--help" ]

cmd/brew.go

Lines changed: 48 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,20 @@ import (
2020
"fmt"
2121
"io/ioutil"
2222
"os"
23+
"os/user"
24+
"path"
2325
"regexp"
26+
"time"
27+
28+
"gopkg.in/src-d/go-git.v4/plumbing/object"
2429

2530
jira "github.com/andygrunwald/go-jira"
2631
log "github.com/sirupsen/logrus"
2732
"github.com/spf13/cobra"
2833
"github.com/spf13/viper"
29-
git "gopkg.in/libgit2/git2go.v27"
34+
"gopkg.in/src-d/go-git.v4"
35+
"gopkg.in/src-d/go-git.v4/plumbing"
36+
"gopkg.in/src-d/go-git.v4/plumbing/format/config"
3037
)
3138

3239
var brewCmd = &cobra.Command{
@@ -77,13 +84,11 @@ func brew(cmd *cobra.Command, args []string) {
7784
panic(err)
7885
}
7986

80-
repo, err := git.OpenRepositoryExtended(cwd, git.RepositoryOpenFromEnv, "")
87+
repo, err := git.PlainOpenWithOptions(cwd, &git.PlainOpenOptions{DetectDotGit: true})
8188
if err != nil {
8289
panic(err)
8390
}
8491

85-
defer repo.Free()
86-
8792
// Get user struct for logged in user
8893
jiraUser, _, err := jiraClient.User.Get(username)
8994
if err != nil {
@@ -231,100 +236,85 @@ func bodyToString(res *jira.Response) string {
231236
}
232237

233238
func checkout(repo *git.Repository, issue *jira.Issue) error {
234-
checkoutOpts := &git.CheckoutOpts{
235-
Strategy: git.CheckoutSafe | git.CheckoutRecreateMissing | git.CheckoutAllowConflicts | git.CheckoutUseTheirs,
239+
workTree, err := repo.Worktree()
240+
if err != nil {
241+
return err
236242
}
237243

238-
// Check only for local branches
239-
branch, err := repo.LookupBranch(issue.Key, git.BranchLocal)
244+
branch := fmt.Sprintf("refs/heads/%s", issue.Key)
245+
b := plumbing.ReferenceName(branch)
246+
247+
// First try to checkout branch
240248
newBranch := false
241-
// If it doesn't exist then create it
242-
if branch == nil || err != nil {
249+
err = workTree.Checkout(&git.CheckoutOptions{Create: false, Force: false, Keep: true, Branch: b})
250+
if err != nil {
251+
// didn't exist so try to create it
243252
newBranch = true
253+
err = workTree.Checkout(&git.CheckoutOptions{Create: true, Force: false, Keep: true, Branch: b})
254+
}
255+
256+
if err != nil {
257+
return err
258+
}
244259

245-
head, err := repo.Head()
260+
if newBranch {
261+
commitMessage := fmt.Sprintf("%s. %s", issue.Key, issue.Fields.Summary)
262+
usr, err := user.Current()
246263
if err != nil {
247264
return err
248265
}
249-
250-
headCommit, err := repo.LookupCommit(head.Target())
266+
gitConfig, err := os.Open(path.Join(usr.HomeDir, ".gitconfig"))
251267
if err != nil {
252268
return err
253269
}
270+
decoder := config.NewDecoder(gitConfig)
271+
decodedConfig := config.New()
272+
err = decoder.Decode(decodedConfig)
254273

255-
branch, err = repo.CreateBranch(issue.Key, headCommit, false)
256274
if err != nil {
257275
return err
258276
}
259-
}
260277

261-
defer branch.Free()
262-
263-
// Get tree for the branch
264-
commit, err := repo.LookupCommit(branch.Target())
265-
if err != nil {
278+
userSection := decodedConfig.Section("user")
279+
_, err = workTree.Commit(commitMessage, &git.CommitOptions{
280+
Author: &object.Signature{
281+
Name: userSection.Option("name"),
282+
Email: userSection.Option("email"),
283+
When: time.Now(),
284+
},
285+
})
266286
return err
267287
}
268-
269-
defer commit.Free()
270-
271-
tree, err := repo.LookupTree(commit.TreeId())
272-
if err != nil {
273-
return err
274-
}
275-
276-
// Checkout the tree
277-
err = repo.CheckoutTree(tree, checkoutOpts)
278-
if err != nil {
279-
return err
280-
}
281-
282-
// Set the head to point to the new branch
283-
repo.SetHead("refs/heads/" + issue.Key)
284-
285-
headCommit, err := repo.LookupCommit(branch.Target())
286-
if err != nil {
287-
return err
288-
}
289-
290-
signature, err := repo.DefaultSignature()
291-
if err != nil {
292-
return err
293-
}
294-
295-
if newBranch {
296-
commitMessage := fmt.Sprintf("%s. %s", issue.Key, issue.Fields.Summary)
297-
_, err = repo.CreateCommit("refs/heads/"+issue.Key, signature, signature, commitMessage, tree, headCommit)
298-
}
288+
299289
return nil
300290
}
301291

302292
func getProjectKey(repo *git.Repository) (string, error) {
303-
head, err := repo.Head()
293+
ref, err := repo.Head()
304294
if err != nil {
305295
return "", err
306296
}
307297

308-
commit, err := repo.LookupCommit(head.Target())
298+
cIter, err := repo.Log(&git.LogOptions{From: ref.Hash()})
309299
if err != nil {
310300
return "", err
311301
}
312302

313303
var depth uint
314-
for depth < 5 {
304+
commit, err := cIter.Next()
305+
for depth < 5 && err != nil {
315306
re := regexp.MustCompile("^([a-zA-Z]{3,})(-[0-9]+)")
316-
message := commit.Message()
307+
message := commit.Message
317308
match := re.FindStringSubmatch(message)
318309
if len(match) == 3 && len(match[1]) > 0 {
319310
log.WithField("project_key", match[1]).Info("Inferred project key; override with --project if incorrect")
320311
return match[1], nil
321312
}
322313
depth++
323-
commit = commit.Parent(0)
314+
commit, err = cIter.Next()
324315
}
325316

326-
defer commit.Free()
327-
return "", errors.New("Wasn't able to infer a project key")
317+
return "", errors.New("wasn't able to infer a project key")
328318
}
329319

330320
func createMetaProject(jira *jira.Client, projectKey string) (*jira.MetaProject, error) {

cmd/taste.go

Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ import (
2222

2323
log "github.com/sirupsen/logrus"
2424
"github.com/spf13/cobra"
25-
git "gopkg.in/libgit2/git2go.v27"
25+
"gopkg.in/src-d/go-git.v4"
26+
"gopkg.in/src-d/go-git.v4/config"
2627
)
2728

2829
var tasteCmd = &cobra.Command{
@@ -57,13 +58,11 @@ func taste(cmd *cobra.Command, args []string) {
5758
panic(err)
5859
}
5960

60-
repo, err := git.OpenRepository(cwd)
61+
repo, err := git.PlainOpenWithOptions(cwd, &git.PlainOpenOptions{DetectDotGit: true})
6162
if err != nil {
6263
panic(err)
6364
}
6465

65-
defer repo.Free()
66-
6766
var ref string
6867
if isWIP {
6968
ref = "master%wip"
@@ -77,38 +76,13 @@ func taste(cmd *cobra.Command, args []string) {
7776
}
7877
log.WithField("refspec", refspec).Debug("Using refspec")
7978

80-
remote, err := repo.Remotes.Lookup("origin")
81-
if err != nil {
82-
panic(err)
83-
}
84-
log.WithField("remote", remote).Debug("Discovered remote")
85-
86-
pushOpts := &git.PushOptions{
87-
RemoteCallbacks: git.RemoteCallbacks{
88-
CredentialsCallback: credentialsCallback,
89-
CertificateCheckCallback: certificateCheckCallback,
90-
SidebandProgressCallback: transportMessageCallback,
91-
},
92-
}
93-
refspecs := []string{refspec}
94-
err = remote.Push(refspecs, pushOpts)
79+
err = repo.Push(&git.PushOptions{
80+
RemoteName: "origin",
81+
RefSpecs: []config.RefSpec{config.RefSpec(refspec)},
82+
})
9583
if err != nil {
9684
log.WithError(err).Error("Error pushing review")
9785
os.Exit(1)
9886
}
9987
log.Info("Pushed review")
10088
}
101-
102-
func credentialsCallback(url string, username string, allowedTypes git.CredType) (git.ErrorCode, *git.Cred) {
103-
ret, cred := git.NewCredSshKeyFromAgent(username)
104-
return git.ErrorCode(ret), &cred
105-
}
106-
107-
func certificateCheckCallback(cert *git.Certificate, valid bool, hostname string) git.ErrorCode {
108-
return 0
109-
}
110-
111-
func transportMessageCallback(str string) git.ErrorCode {
112-
fmt.Printf(str)
113-
return 0
114-
}

go.mod

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,11 @@ require (
77
github.com/google/go-querystring v1.0.0 // indirect
88
github.com/inconshreveable/mousetrap v1.0.0 // indirect
99
github.com/mitchellh/go-homedir v1.1.0
10-
github.com/pkg/errors v0.8.1 // indirect
1110
github.com/sirupsen/logrus v1.3.0
1211
github.com/spf13/afero v1.2.0 // indirect
1312
github.com/spf13/cobra v0.0.3
1413
github.com/spf13/viper v1.3.1
1514
github.com/trivago/tgo v1.0.5 // indirect
16-
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b // indirect
17-
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e // indirect
18-
gopkg.in/libgit2/git2go.v27 v27.0.0-20190104134018-ecaeb7a21d47
15+
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 // indirect
16+
gopkg.in/src-d/go-git.v4 v4.12.0
1917
)

0 commit comments

Comments
 (0)