aboutsummaryrefslogtreecommitdiffstats
path: root/bridge/github
diff options
context:
space:
mode:
Diffstat (limited to 'bridge/github')
-rw-r--r--bridge/github/github.go4
-rw-r--r--bridge/github/import.go34
-rw-r--r--bridge/github/import_test.go148
-rw-r--r--bridge/github/iterator.go154
4 files changed, 169 insertions, 171 deletions
diff --git a/bridge/github/github.go b/bridge/github/github.go
index b3f8d763..5fee7487 100644
--- a/bridge/github/github.go
+++ b/bridge/github/github.go
@@ -27,9 +27,9 @@ func (*Github) NewExporter() core.Exporter {
return nil
}
-func buildClient(conf core.Configuration) *githubv4.Client {
+func buildClient(token string) *githubv4.Client {
src := oauth2.StaticTokenSource(
- &oauth2.Token{AccessToken: conf[keyToken]},
+ &oauth2.Token{AccessToken: token},
)
httpClient := oauth2.NewClient(context.TODO(), src)
diff --git a/bridge/github/import.go b/bridge/github/import.go
index 5f99b5ea..ad9d5046 100644
--- a/bridge/github/import.go
+++ b/bridge/github/import.go
@@ -22,29 +22,27 @@ const (
// githubImporter implement the Importer interface
type githubImporter struct {
- iterator *iterator
- conf core.Configuration
+ conf core.Configuration
}
func (gi *githubImporter) Init(conf core.Configuration) error {
gi.conf = conf
- gi.iterator = newIterator(conf)
return nil
}
// ImportAll .
func (gi *githubImporter) ImportAll(repo *cache.RepoCache, since time.Time) error {
- gi.iterator.since = since
+ iterator := NewIterator(gi.conf[keyUser], gi.conf[keyProject], gi.conf[keyToken], since)
// Loop over all matching issues
- for gi.iterator.NextIssue() {
- issue := gi.iterator.IssueValue()
+ for iterator.NextIssue() {
+ issue := iterator.IssueValue()
- fmt.Printf("importing issue: %v %v\n", gi.iterator.count, issue.Title)
+ fmt.Printf("importing issue: %v %v\n", iterator.importedIssues, issue.Title)
// get issue edits
issueEdits := []userContentEdit{}
- for gi.iterator.NextIssueEdit() {
- if issueEdit := gi.iterator.IssueEditValue(); issueEdit.Diff != nil && string(*issueEdit.Diff) != "" {
+ for iterator.NextIssueEdit() {
+ if issueEdit := iterator.IssueEditValue(); issueEdit.Diff != nil && string(*issueEdit.Diff) != "" {
issueEdits = append(issueEdits, issueEdit)
}
}
@@ -56,15 +54,15 @@ func (gi *githubImporter) ImportAll(repo *cache.RepoCache, since time.Time) erro
}
// loop over timeline items
- for gi.iterator.NextTimeline() {
- item := gi.iterator.TimelineValue()
+ for iterator.NextTimeline() {
+ item := iterator.TimelineValue()
// if item is comment
if item.Typename == "IssueComment" {
// collect all edits
commentEdits := []userContentEdit{}
- for gi.iterator.NextCommentEdit() {
- if commentEdit := gi.iterator.CommentEditValue(); commentEdit.Diff != nil && string(*commentEdit.Diff) != "" {
+ for iterator.NextCommentEdit() {
+ if commentEdit := iterator.CommentEditValue(); commentEdit.Diff != nil && string(*commentEdit.Diff) != "" {
commentEdits = append(commentEdits, commentEdit)
}
}
@@ -87,12 +85,12 @@ func (gi *githubImporter) ImportAll(repo *cache.RepoCache, since time.Time) erro
}
}
- if err := gi.iterator.Error(); err != nil {
+ if err := iterator.Error(); err != nil {
fmt.Printf("import error: %v\n", err)
return err
}
- fmt.Printf("Successfully imported %v issues from Github\n", gi.iterator.Count())
+ fmt.Printf("Successfully imported %v issues from Github\n", iterator.ImportedIssues())
return nil
}
@@ -389,7 +387,7 @@ func (gi *githubImporter) ensureCommentEdit(repo *cache.RepoCache, b *cache.BugC
switch {
case edit.DeletedAt != nil:
// comment deletion, not supported yet
- fmt.Println("comment deletion ....")
+ fmt.Println("comment deletion is not supported yet")
case edit.DeletedAt == nil:
@@ -475,7 +473,9 @@ func (gi *githubImporter) getGhost(repo *cache.RepoCache) (*cache.IdentityCache,
"login": githubv4.String("ghost"),
}
- err = gi.iterator.gc.Query(context.TODO(), &q, variables)
+ gc := buildClient(gi.conf[keyToken])
+
+ err = gc.Query(context.TODO(), &q, variables)
if err != nil {
return nil, err
}
diff --git a/bridge/github/import_test.go b/bridge/github/import_test.go
index d64f0b4b..79af8450 100644
--- a/bridge/github/import_test.go
+++ b/bridge/github/import_test.go
@@ -18,15 +18,13 @@ import (
func Test_Importer(t *testing.T) {
author := identity.NewIdentity("Michael Muré", "batolettre@gmail.com")
tests := []struct {
- name string
- exist bool
- url string
- bug *bug.Snapshot
+ name string
+ url string
+ bug *bug.Snapshot
}{
{
- name: "simple issue",
- exist: true,
- url: "https://github.com/MichaelMure/git-but-test-github-bridge/issues/1",
+ name: "simple issue",
+ url: "https://github.com/MichaelMure/git-but-test-github-bridge/issues/1",
bug: &bug.Snapshot{
Operations: []bug.Operation{
bug.NewCreateOp(author, 0, "simple issue", "initial comment", nil),
@@ -35,9 +33,8 @@ func Test_Importer(t *testing.T) {
},
},
{
- name: "empty issue",
- exist: true,
- url: "https://github.com/MichaelMure/git-but-test-github-bridge/issues/2",
+ name: "empty issue",
+ url: "https://github.com/MichaelMure/git-but-test-github-bridge/issues/2",
bug: &bug.Snapshot{
Operations: []bug.Operation{
bug.NewCreateOp(author, 0, "empty issue", "", nil),
@@ -45,9 +42,8 @@ func Test_Importer(t *testing.T) {
},
},
{
- name: "complex issue",
- exist: true,
- url: "https://github.com/MichaelMure/git-but-test-github-bridge/issues/3",
+ name: "complex issue",
+ url: "https://github.com/MichaelMure/git-but-test-github-bridge/issues/3",
bug: &bug.Snapshot{
Operations: []bug.Operation{
bug.NewCreateOp(author, 0, "complex issue", "initial comment", nil),
@@ -63,9 +59,8 @@ func Test_Importer(t *testing.T) {
},
},
{
- name: "editions",
- exist: true,
- url: "https://github.com/MichaelMure/git-but-test-github-bridge/issues/4",
+ name: "editions",
+ url: "https://github.com/MichaelMure/git-but-test-github-bridge/issues/4",
bug: &bug.Snapshot{
Operations: []bug.Operation{
bug.NewCreateOp(author, 0, "editions", "initial comment edited", nil),
@@ -76,9 +71,8 @@ func Test_Importer(t *testing.T) {
},
},
{
- name: "comment deletion",
- exist: true,
- url: "https://github.com/MichaelMure/git-but-test-github-bridge/issues/5",
+ name: "comment deletion",
+ url: "https://github.com/MichaelMure/git-but-test-github-bridge/issues/5",
bug: &bug.Snapshot{
Operations: []bug.Operation{
bug.NewCreateOp(author, 0, "comment deletion", "", nil),
@@ -86,9 +80,8 @@ func Test_Importer(t *testing.T) {
},
},
{
- name: "edition deletion",
- exist: true,
- url: "https://github.com/MichaelMure/git-but-test-github-bridge/issues/6",
+ name: "edition deletion",
+ url: "https://github.com/MichaelMure/git-but-test-github-bridge/issues/6",
bug: &bug.Snapshot{
Operations: []bug.Operation{
bug.NewCreateOp(author, 0, "edition deletion", "initial comment", nil),
@@ -99,9 +92,8 @@ func Test_Importer(t *testing.T) {
},
},
{
- name: "hidden comment",
- exist: true,
- url: "https://github.com/MichaelMure/git-but-test-github-bridge/issues/7",
+ name: "hidden comment",
+ url: "https://github.com/MichaelMure/git-but-test-github-bridge/issues/7",
bug: &bug.Snapshot{
Operations: []bug.Operation{
bug.NewCreateOp(author, 0, "hidden comment", "initial comment", nil),
@@ -110,9 +102,8 @@ func Test_Importer(t *testing.T) {
},
},
{
- name: "transfered issue",
- exist: true,
- url: "https://github.com/MichaelMure/git-but-test-github-bridge/issues/8",
+ name: "transfered issue",
+ url: "https://github.com/MichaelMure/git-but-test-github-bridge/issues/8",
bug: &bug.Snapshot{
Operations: []bug.Operation{
bug.NewCreateOp(author, 0, "transfered issue", "", nil),
@@ -139,11 +130,16 @@ func Test_Importer(t *testing.T) {
defer backend.Close()
interrupt.RegisterCleaner(backend.Close)
+ token := os.Getenv("GITHUB_TOKEN")
+ if token == "" {
+ t.Skip("Env var GITHUB_TOKEN missing")
+ }
+
importer := &githubImporter{}
err = importer.Init(core.Configuration{
"user": "MichaelMure",
"project": "git-but-test-github-bridge",
- "token": os.Getenv("GITHUB_TOKEN"),
+ "token": token,
})
if err != nil {
t.Fatal(err)
@@ -165,59 +161,53 @@ func Test_Importer(t *testing.T) {
}
ops := b.Snapshot().Operations
- if tt.exist {
- assert.Equal(t, len(tt.bug.Operations), len(b.Snapshot().Operations))
-
- for i, op := range tt.bug.Operations {
- switch op.(type) {
- case *bug.CreateOperation:
- if op2, ok := ops[i].(*bug.CreateOperation); ok {
- assert.Equal(t, op2.Title, op.(*bug.CreateOperation).Title)
- assert.Equal(t, op2.Message, op.(*bug.CreateOperation).Message)
- continue
- }
- t.Errorf("bad operation type index = %d expected = CreationOperation", i)
- case *bug.SetStatusOperation:
- if op2, ok := ops[i].(*bug.SetStatusOperation); ok {
- assert.Equal(t, op2.Status, op.(*bug.SetStatusOperation).Status)
- continue
- }
- t.Errorf("bad operation type index = %d expected = SetStatusOperation", i)
- case *bug.SetTitleOperation:
- if op2, ok := ops[i].(*bug.SetTitleOperation); ok {
- assert.Equal(t, op.(*bug.SetTitleOperation).Was, op2.Was)
- assert.Equal(t, op.(*bug.SetTitleOperation).Title, op2.Title)
- continue
- }
- t.Errorf("bad operation type index = %d expected = SetTitleOperation", i)
- case *bug.LabelChangeOperation:
- if op2, ok := ops[i].(*bug.LabelChangeOperation); ok {
- assert.ElementsMatch(t, op.(*bug.LabelChangeOperation).Added, op2.Added)
- assert.ElementsMatch(t, op.(*bug.LabelChangeOperation).Removed, op2.Removed)
- continue
- }
- t.Errorf("bad operation type index = %d expected = ChangeLabelOperation", i)
- case *bug.AddCommentOperation:
- if op2, ok := ops[i].(*bug.AddCommentOperation); ok {
- assert.Equal(t, op.(*bug.AddCommentOperation).Message, op2.Message)
- continue
- }
- t.Errorf("bad operation type index = %d expected = AddCommentOperation", i)
- case *bug.EditCommentOperation:
- if op2, ok := ops[i].(*bug.EditCommentOperation); ok {
- assert.Equal(t, op.(*bug.EditCommentOperation).Message, op2.Message)
- continue
- }
- t.Errorf("bad operation type index = %d expected = EditCommentOperation", i)
- default:
-
+ assert.Equal(t, len(tt.bug.Operations), len(b.Snapshot().Operations))
+
+ for i, op := range tt.bug.Operations {
+ switch op.(type) {
+ case *bug.CreateOperation:
+ if op2, ok := ops[i].(*bug.CreateOperation); ok {
+ assert.Equal(t, op2.Title, op.(*bug.CreateOperation).Title)
+ assert.Equal(t, op2.Message, op.(*bug.CreateOperation).Message)
+ continue
+ }
+ t.Errorf("bad operation type index = %d expected = CreationOperation", i)
+ case *bug.SetStatusOperation:
+ if op2, ok := ops[i].(*bug.SetStatusOperation); ok {
+ assert.Equal(t, op2.Status, op.(*bug.SetStatusOperation).Status)
+ continue
+ }
+ t.Errorf("bad operation type index = %d expected = SetStatusOperation", i)
+ case *bug.SetTitleOperation:
+ if op2, ok := ops[i].(*bug.SetTitleOperation); ok {
+ assert.Equal(t, op.(*bug.SetTitleOperation).Was, op2.Was)
+ assert.Equal(t, op.(*bug.SetTitleOperation).Title, op2.Title)
+ continue
}
+ t.Errorf("bad operation type index = %d expected = SetTitleOperation", i)
+ case *bug.LabelChangeOperation:
+ if op2, ok := ops[i].(*bug.LabelChangeOperation); ok {
+ assert.ElementsMatch(t, op.(*bug.LabelChangeOperation).Added, op2.Added)
+ assert.ElementsMatch(t, op.(*bug.LabelChangeOperation).Removed, op2.Removed)
+ continue
+ }
+ t.Errorf("bad operation type index = %d expected = ChangeLabelOperation", i)
+ case *bug.AddCommentOperation:
+ if op2, ok := ops[i].(*bug.AddCommentOperation); ok {
+ assert.Equal(t, op.(*bug.AddCommentOperation).Message, op2.Message)
+ continue
+ }
+ t.Errorf("bad operation type index = %d expected = AddCommentOperation", i)
+ case *bug.EditCommentOperation:
+ if op2, ok := ops[i].(*bug.EditCommentOperation); ok {
+ assert.Equal(t, op.(*bug.EditCommentOperation).Message, op2.Message)
+ continue
+ }
+ t.Errorf("bad operation type index = %d expected = EditCommentOperation", i)
+ default:
+ panic("Unknown operation type")
}
-
- } else {
- assert.Equal(t, b, nil)
}
})
}
-
}
diff --git a/bridge/github/iterator.go b/bridge/github/iterator.go
index 281f8a6b..239b49bd 100644
--- a/bridge/github/iterator.go
+++ b/bridge/github/iterator.go
@@ -4,7 +4,6 @@ import (
"context"
"time"
- "github.com/MichaelMure/git-bug/bridge/core"
"github.com/shurcooL/githubv4"
)
@@ -50,8 +49,8 @@ type iterator struct {
// sticky error
err error
- // count to keep track of the number of imported issues
- count int
+ // number of imported issues
+ importedIssues int
// timeline iterator
timeline timelineIterator
@@ -63,32 +62,32 @@ type iterator struct {
commentEdit commentEditIterator
}
-func newIterator(conf core.Configuration) *iterator {
+func NewIterator(user, project, token string, since time.Time) *iterator {
return &iterator{
- gc: buildClient(conf),
+ gc: buildClient(token),
+ since: since,
capacity: 10,
- count: 0,
timeline: timelineIterator{
index: -1,
issueEdit: indexer{-1},
commentEdit: indexer{-1},
variables: map[string]interface{}{
- "owner": githubv4.String(conf["user"]),
- "name": githubv4.String(conf["project"]),
+ "owner": githubv4.String(user),
+ "name": githubv4.String(project),
},
},
commentEdit: commentEditIterator{
index: -1,
variables: map[string]interface{}{
- "owner": githubv4.String(conf["user"]),
- "name": githubv4.String(conf["project"]),
+ "owner": githubv4.String(user),
+ "name": githubv4.String(project),
},
},
issueEdit: issueEditIterator{
index: -1,
variables: map[string]interface{}{
- "owner": githubv4.String(conf["user"]),
- "name": githubv4.String(conf["project"]),
+ "owner": githubv4.String(user),
+ "name": githubv4.String(project),
},
},
}
@@ -130,10 +129,11 @@ func (i *iterator) initCommentEditQueryVariables() {
// reverse UserContentEdits arrays in both of the issue and
// comment timelines
func (i *iterator) reverseTimelineEditNodes() {
- reverseEdits(i.timeline.query.Repository.Issues.Nodes[0].UserContentEdits.Nodes)
- for index, ce := range i.timeline.query.Repository.Issues.Nodes[0].Timeline.Edges {
- if ce.Node.Typename == "IssueComment" && len(i.timeline.query.Repository.Issues.Nodes[0].Timeline.Edges) != 0 {
- reverseEdits(i.timeline.query.Repository.Issues.Nodes[0].Timeline.Edges[index].Node.IssueComment.UserContentEdits.Nodes)
+ node := i.timeline.query.Repository.Issues.Nodes[0]
+ reverseEdits(node.UserContentEdits.Nodes)
+ for index, ce := range node.Timeline.Edges {
+ if ce.Node.Typename == "IssueComment" && len(node.Timeline.Edges) != 0 {
+ reverseEdits(node.Timeline.Edges[index].Node.IssueComment.UserContentEdits.Nodes)
}
}
}
@@ -143,19 +143,34 @@ func (i *iterator) Error() error {
return i.err
}
-// Count return number of issues we iterated over
-func (i *iterator) Count() int {
- return i.count
+// ImportedIssues return the number of issues we iterated over
+func (i *iterator) ImportedIssues() int {
+ return i.importedIssues
+}
+
+func (i *iterator) queryIssue() bool {
+ if err := i.gc.Query(context.TODO(), &i.timeline.query, i.timeline.variables); err != nil {
+ i.err = err
+ return false
+ }
+
+ if len(i.timeline.query.Repository.Issues.Nodes) == 0 {
+ return false
+ }
+
+ i.reverseTimelineEditNodes()
+ i.importedIssues++
+ return true
}
// Next issue
func (i *iterator) NextIssue() bool {
// we make the first move
- if i.count == 0 {
+ if i.importedIssues == 0 {
// init variables and goto queryIssue block
i.initTimelineQueryVariables()
- goto queryIssue
+ return i.queryIssue()
}
if i.err != nil {
@@ -175,19 +190,7 @@ func (i *iterator) NextIssue() bool {
i.timeline.lastEndCursor = i.timeline.query.Repository.Issues.Nodes[0].Timeline.PageInfo.EndCursor
// query issue block
-queryIssue:
- if err := i.gc.Query(context.TODO(), &i.timeline.query, i.timeline.variables); err != nil {
- i.err = err
- return false
- }
-
- if len(i.timeline.query.Repository.Issues.Nodes) == 0 {
- return false
- }
-
- i.reverseTimelineEditNodes()
- i.count++
- return true
+ return i.queryIssue()
}
func (i *iterator) IssueValue() issueTimeline {
@@ -230,6 +233,27 @@ func (i *iterator) TimelineValue() timelineItem {
return i.timeline.query.Repository.Issues.Nodes[0].Timeline.Edges[i.timeline.index].Node
}
+func (i *iterator) queryIssueEdit() bool {
+ if err := i.gc.Query(context.TODO(), &i.issueEdit.query, i.issueEdit.variables); err != nil {
+ i.err = err
+ //i.timeline.issueEdit.index = -1
+ return false
+ }
+
+ // reverse issue edits because github
+ reverseEdits(i.issueEdit.query.Repository.Issues.Nodes[0].UserContentEdits.Nodes)
+
+ // this is not supposed to happen
+ if len(i.issueEdit.query.Repository.Issues.Nodes[0].UserContentEdits.Nodes) == 0 {
+ i.timeline.issueEdit.index = -1
+ return false
+ }
+
+ i.issueEdit.index = 0
+ i.timeline.issueEdit.index = -2
+ return true
+}
+
func (i *iterator) NextIssueEdit() bool {
if i.err != nil {
return false
@@ -251,7 +275,7 @@ func (i *iterator) NextIssueEdit() bool {
// if there is more edits, query them
i.issueEdit.variables["issueEditBefore"] = i.issueEdit.query.Repository.Issues.Nodes[0].UserContentEdits.PageInfo.StartCursor
- goto queryIssueEdit
+ return i.queryIssueEdit()
}
// if there is no edits
@@ -273,26 +297,7 @@ func (i *iterator) NextIssueEdit() bool {
// if there is more edits, query them
i.initIssueEditQueryVariables()
i.issueEdit.variables["issueEditBefore"] = i.timeline.query.Repository.Issues.Nodes[0].UserContentEdits.PageInfo.StartCursor
-
-queryIssueEdit:
- if err := i.gc.Query(context.TODO(), &i.issueEdit.query, i.issueEdit.variables); err != nil {
- i.err = err
- //i.timeline.issueEdit.index = -1
- return false
- }
-
- // reverse issue edits because github
- reverseEdits(i.issueEdit.query.Repository.Issues.Nodes[0].UserContentEdits.Nodes)
-
- // this is not supposed to happen
- if len(i.issueEdit.query.Repository.Issues.Nodes[0].UserContentEdits.Nodes) == 0 {
- i.timeline.issueEdit.index = -1
- return false
- }
-
- i.issueEdit.index = 0
- i.timeline.issueEdit.index = -2
- return true
+ return i.queryIssueEdit()
}
func (i *iterator) IssueEditValue() userContentEdit {
@@ -305,6 +310,25 @@ func (i *iterator) IssueEditValue() userContentEdit {
return i.timeline.query.Repository.Issues.Nodes[0].UserContentEdits.Nodes[i.timeline.issueEdit.index]
}
+func (i *iterator) queryCommentEdit() bool {
+ if err := i.gc.Query(context.TODO(), &i.commentEdit.query, i.commentEdit.variables); err != nil {
+ i.err = err
+ return false
+ }
+
+ // this is not supposed to happen
+ if len(i.commentEdit.query.Repository.Issues.Nodes[0].Timeline.Nodes[0].IssueComment.UserContentEdits.Nodes) == 0 {
+ i.timeline.commentEdit.index = -1
+ return false
+ }
+
+ reverseEdits(i.commentEdit.query.Repository.Issues.Nodes[0].Timeline.Nodes[0].IssueComment.UserContentEdits.Nodes)
+
+ i.commentEdit.index = 0
+ i.timeline.commentEdit.index = -2
+ return true
+}
+
func (i *iterator) NextCommentEdit() bool {
if i.err != nil {
return false
@@ -326,7 +350,7 @@ func (i *iterator) NextCommentEdit() bool {
// if there is more comment edits, query them
i.commentEdit.variables["commentEditBefore"] = i.commentEdit.query.Repository.Issues.Nodes[0].Timeline.Nodes[0].IssueComment.UserContentEdits.PageInfo.StartCursor
- goto queryCommentEdit
+ return i.queryCommentEdit()
}
// if there is no comment edits
@@ -354,23 +378,7 @@ func (i *iterator) NextCommentEdit() bool {
i.commentEdit.variables["commentEditBefore"] = i.timeline.query.Repository.Issues.Nodes[0].Timeline.Edges[i.timeline.index].Node.IssueComment.UserContentEdits.PageInfo.StartCursor
-queryCommentEdit:
- if err := i.gc.Query(context.TODO(), &i.commentEdit.query, i.commentEdit.variables); err != nil {
- i.err = err
- return false
- }
-
- // this is not supposed to happen
- if len(i.commentEdit.query.Repository.Issues.Nodes[0].Timeline.Nodes[0].IssueComment.UserContentEdits.Nodes) == 0 {
- i.timeline.commentEdit.index = -1
- return false
- }
-
- reverseEdits(i.commentEdit.query.Repository.Issues.Nodes[0].Timeline.Nodes[0].IssueComment.UserContentEdits.Nodes)
-
- i.commentEdit.index = 0
- i.timeline.commentEdit.index = -2
- return true
+ return i.queryCommentEdit()
}
func (i *iterator) CommentEditValue() userContentEdit {