-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathsync.go
120 lines (99 loc) · 2.78 KB
/
sync.go
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
package main
import (
"encoding/hex"
"log"
"github.com/libgit2/git2go"
"github.com/pipeviz/pipeviz/message"
"github.com/pipeviz/pipeviz/types/semantic"
"github.com/spf13/cobra"
)
type syncCmd struct {
all bool
}
func syncCommand() *cobra.Command {
sync := &syncCmd{}
cmd := &cobra.Command{
Use: "sync [-a|--all] <repository>",
Short: "Sends state of all local refs, and optionally all reachable local commits, to a pipeviz server",
Run: sync.run,
}
cmd.Flags().BoolVarP(&sync.all, "all", "a", false, "Send all commit history info in addition to all refs.")
return cmd
}
func (s *syncCmd) run(cmd *cobra.Command, args []string) {
syncHistory(getRepoOrExit(args...), s.all)
}
func syncHistory(repo *git.Repository, all bool) {
var err error
var ident string
msg := newMessage()
if all {
ident, err = GetRepoIdent(repo)
if err != nil {
log.Fatalf("Failed to retrieve a stable identifier for this repository; cannot formulate commits correctly. Aborting.")
}
}
cvisited := make(map[git.Oid]struct{})
iter, err := repo.NewReferenceIterator()
if err != nil {
log.Fatalln("Error while creating reference iterator:", err)
}
// For simplicity, create a revwalker now even if we don't use it later
w, err := repo.Walk()
if err != nil {
log.Fatalln("Could not create revwalker iterator:", err)
}
w.Sorting(git.SortTopological)
//defer w.Free()
for ref, err := iter.Next(); err == nil; ref, err = iter.Next() {
// in func for easy defer of Free()
func(r *git.Reference, m *message.Message) {
//defer r.Free()
oid := r.Target()
if !r.IsBranch() && !r.IsTag() {
return
}
if r.IsBranch() {
bn, _ := r.Branch().Name()
w.Push(oid)
m.Add(semantic.CommitMeta{
Sha1Str: hex.EncodeToString(oid[:]),
Tags: make([]string, 0),
Branches: []string{bn},
})
} else if r.IsTag() {
w.Push(oid)
m.Add(semantic.CommitMeta{
Sha1Str: hex.EncodeToString(oid[:]),
// TODO this still emits the refs/tags/<name> form, ugh
Tags: []string{r.Name()},
Branches: make([]string, 0),
})
} else {
log.Fatalf("Ref %s is neither branch nor tag - wtf\n", r.Name())
}
}(ref, msg)
}
//iter.Free()
if err != nil {
if !git.IsErrorCode(err, git.ErrIterOver) {
//if gerr, ok := err.(*git.GitError); !ok || gerr.Code != git.ErrIterOver {
gerr := err.(*git.GitError)
log.Fatalf("Iteration through repository refs terminated with unexpected error (code: %d, message: %q)\n", gerr.Code, gerr.Message)
}
}
if all {
w.Iterate(func(c *git.Commit) bool {
//defer c.Free()
if _, exists := cvisited[*c.Id()]; exists {
return false
}
cvisited[*c.Id()] = struct{}{}
msg.Add(commitToSemanticForm(c, ident))
return true
})
}
//w.Free()
recordHead(msg, repo)
sendMapToPipeviz(msg, repo)
}