diff options
author | Amine Hilaly <hilalyamine@gmail.com> | 2019-08-13 19:51:14 +0200 |
---|---|---|
committer | Amine Hilaly <hilalyamine@gmail.com> | 2019-08-18 00:14:22 +0200 |
commit | 5ca326af83b90531d4d0c502bb1beabbe1b48c55 (patch) | |
tree | 6b7a32f2db9ab7321e9965c0ef4c715c6c517178 /bridge/gitlab/import.go | |
parent | 6428352bd14828f670206b60862de7f71c52d235 (diff) | |
download | git-bug-5ca326af83b90531d4d0c502bb1beabbe1b48c55.tar.gz |
bridge/core: add context.Context to ImportAll and ExportAll signatures
bridge/core: add ImportResult objects to stream import events
bridge/core: launchpad support asynchronous import
bridge/github: cancellable export and import functions
bridge/gitlab: cancellable export and import functions
commands: bridge pull/push gracefull kill
bridge/github: fix github import
bridge/github: use simple context for imports
bridge/core: name parameters in interfaces
github/core: Add EventError to export and import events types
bridge/gitlab: add context support in gitlab requests functions
bridge/gitlab: remove imported events count from importer logic
bridge/github: remove imported events count from importer logic
bridge/github: add context support in query and muration requets
bridge/github: fix bug duplicate editions after multiple calls
bridge/core: import import and export events String methods
bridge/gitlab: fix error handling in note import events
commands/bridge: Add statistics about imports and exports
bridge/gitlab: properly handle context cancellation
bridge/github: improve error handling
bridge: break iterators on context cancel or timeout
bridge: add context timeout support
bridge: improve event formating and error handling
commands: handle interrupt and switch cases
bridge/github: add export mutation timeouts
bridge: fix race condition bug in the github and gitlab importers
bridge/github: improve context error handling
Diffstat (limited to 'bridge/gitlab/import.go')
-rw-r--r-- | bridge/gitlab/import.go | 156 |
1 files changed, 96 insertions, 60 deletions
diff --git a/bridge/gitlab/import.go b/bridge/gitlab/import.go index e135b8bc..40ac06d3 100644 --- a/bridge/gitlab/import.go +++ b/bridge/gitlab/import.go @@ -1,6 +1,7 @@ package gitlab import ( + "context" "fmt" "strconv" "time" @@ -21,11 +22,8 @@ type gitlabImporter struct { // iterator iterator *iterator - // number of imported issues - importedIssues int - - // number of imported identities - importedIdentities int + // send only channel + out chan<- core.ImportResult } func (gi *gitlabImporter) Init(conf core.Configuration) error { @@ -35,49 +33,60 @@ func (gi *gitlabImporter) Init(conf core.Configuration) error { // ImportAll iterate over all the configured repository issues (notes) and ensure the creation // of the missing issues / comments / label events / title changes ... -func (gi *gitlabImporter) ImportAll(repo *cache.RepoCache, since time.Time) error { - gi.iterator = NewIterator(gi.conf[keyProjectID], gi.conf[keyToken], since) - - // Loop over all matching issues - for gi.iterator.NextIssue() { - issue := gi.iterator.IssueValue() - fmt.Printf("importing issue: %v\n", issue.Title) +func (gi *gitlabImporter) ImportAll(ctx context.Context, repo *cache.RepoCache, since time.Time) (<-chan core.ImportResult, error) { + gi.iterator = NewIterator(ctx, 10, gi.conf[keyProjectID], gi.conf[keyToken], since) + out := make(chan core.ImportResult) + gi.out = out + + go func() { + defer close(gi.out) + + // Loop over all matching issues + for gi.iterator.NextIssue() { + issue := gi.iterator.IssueValue() + + // create issue + b, err := gi.ensureIssue(repo, issue) + if err != nil { + err := fmt.Errorf("issue creation: %v", err) + out <- core.NewImportError(err, "") + return + } - // create issue - b, err := gi.ensureIssue(repo, issue) - if err != nil { - return fmt.Errorf("issue creation: %v", err) - } + // Loop over all notes + for gi.iterator.NextNote() { + note := gi.iterator.NoteValue() + if err := gi.ensureNote(repo, b, note); err != nil { + err := fmt.Errorf("note creation: %v", err) + out <- core.NewImportError(err, entity.Id(strconv.Itoa(note.ID))) + return + } + } - // Loop over all notes - for gi.iterator.NextNote() { - note := gi.iterator.NoteValue() - if err := gi.ensureNote(repo, b, note); err != nil { - return fmt.Errorf("note creation: %v", err) + // Loop over all label events + for gi.iterator.NextLabelEvent() { + labelEvent := gi.iterator.LabelEventValue() + if err := gi.ensureLabelEvent(repo, b, labelEvent); err != nil { + err := fmt.Errorf("label event creation: %v", err) + out <- core.NewImportError(err, entity.Id(strconv.Itoa(labelEvent.ID))) + return + } } - } - // Loop over all label events - for gi.iterator.NextLabelEvent() { - labelEvent := gi.iterator.LabelEventValue() - if err := gi.ensureLabelEvent(repo, b, labelEvent); err != nil { - return fmt.Errorf("label event creation: %v", err) + // commit bug state + if err := b.CommitAsNeeded(); err != nil { + err := fmt.Errorf("bug commit: %v", err) + out <- core.NewImportError(err, "") + return } } if err := gi.iterator.Error(); err != nil { - fmt.Printf("import error: %v\n", err) - return err + out <- core.NewImportError(err, "") } + }() - // commit bug state - if err := b.CommitAsNeeded(); err != nil { - return fmt.Errorf("bug commit: %v", err) - } - } - - fmt.Printf("Successfully imported %d issues and %d identities from Gitlab\n", gi.importedIssues, gi.importedIdentities) - return nil + return out, nil } func (gi *gitlabImporter) ensureIssue(repo *cache.RepoCache, issue *gitlab.Issue) (*cache.BugCache, error) { @@ -89,13 +98,14 @@ func (gi *gitlabImporter) ensureIssue(repo *cache.RepoCache, issue *gitlab.Issue // resolve bug b, err := repo.ResolveBugCreateMetadata(keyGitlabUrl, issue.WebURL) - if err != nil && err != bug.ErrBugNotExist { - return nil, err - } - if err == nil { + reason := fmt.Sprintf("bug already imported") + gi.out <- core.NewImportNothing("", reason) return b, nil } + if err != bug.ErrBugNotExist { + return nil, err + } // if bug was never imported cleanText, err := text.Cleanup(issue.Description) @@ -123,7 +133,7 @@ func (gi *gitlabImporter) ensureIssue(repo *cache.RepoCache, issue *gitlab.Issue } // importing a new bug - gi.importedIssues++ + gi.out <- core.NewImportBug(b.Id()) return b, nil } @@ -149,28 +159,36 @@ func (gi *gitlabImporter) ensureNote(repo *cache.RepoCache, b *cache.BugCache, n return nil } - _, err = b.CloseRaw( + op, err := b.CloseRaw( author, note.CreatedAt.Unix(), map[string]string{ keyGitlabId: gitlabID, }, ) - return err + if err != nil { + return err + } + + gi.out <- core.NewImportStatusChange(op.Id()) case NOTE_REOPENED: if errResolve == nil { return nil } - _, err = b.OpenRaw( + op, err := b.OpenRaw( author, note.CreatedAt.Unix(), map[string]string{ keyGitlabId: gitlabID, }, ) - return err + if err != nil { + return err + } + + gi.out <- core.NewImportStatusChange(op.Id()) case NOTE_DESCRIPTION_CHANGED: issue := gi.iterator.IssueValue() @@ -181,7 +199,7 @@ func (gi *gitlabImporter) ensureNote(repo *cache.RepoCache, b *cache.BugCache, n // TODO: Check only one time and ignore next 'description change' within one issue if errResolve == cache.ErrNoMatchingOp && issue.Description != firstComment.Message { // comment edition - _, err = b.EditCommentRaw( + op, err := b.EditCommentRaw( author, note.UpdatedAt.Unix(), firstComment.Id(), @@ -190,8 +208,11 @@ func (gi *gitlabImporter) ensureNote(repo *cache.RepoCache, b *cache.BugCache, n keyGitlabId: gitlabID, }, ) + if err != nil { + return err + } - return err + gi.out <- core.NewImportTitleEdition(op.Id()) } case NOTE_COMMENT: @@ -204,7 +225,7 @@ func (gi *gitlabImporter) ensureNote(repo *cache.RepoCache, b *cache.BugCache, n if errResolve == cache.ErrNoMatchingOp { // add comment operation - _, err = b.AddCommentRaw( + op, err := b.AddCommentRaw( author, note.CreatedAt.Unix(), cleanText, @@ -213,8 +234,11 @@ func (gi *gitlabImporter) ensureNote(repo *cache.RepoCache, b *cache.BugCache, n keyGitlabId: gitlabID, }, ) - - return err + if err != nil { + return err + } + gi.out <- core.NewImportComment(op.Id()) + return nil } // if comment was already exported @@ -228,7 +252,7 @@ func (gi *gitlabImporter) ensureNote(repo *cache.RepoCache, b *cache.BugCache, n // compare local bug comment with the new note body if comment.Message != cleanText { // comment edition - _, err = b.EditCommentRaw( + op, err := b.EditCommentRaw( author, note.UpdatedAt.Unix(), comment.Id(), @@ -236,7 +260,10 @@ func (gi *gitlabImporter) ensureNote(repo *cache.RepoCache, b *cache.BugCache, n nil, ) - return err + if err != nil { + return err + } + gi.out <- core.NewImportCommentEdition(op.Id()) } return nil @@ -247,7 +274,7 @@ func (gi *gitlabImporter) ensureNote(repo *cache.RepoCache, b *cache.BugCache, n return nil } - _, err = b.SetTitleRaw( + op, err := b.SetTitleRaw( author, note.CreatedAt.Unix(), body, @@ -255,8 +282,11 @@ func (gi *gitlabImporter) ensureNote(repo *cache.RepoCache, b *cache.BugCache, n keyGitlabId: gitlabID, }, ) + if err != nil { + return err + } - return err + gi.out <- core.NewImportTitleEdition(op.Id()) case NOTE_UNKNOWN, NOTE_ASSIGNED, @@ -269,6 +299,9 @@ func (gi *gitlabImporter) ensureNote(repo *cache.RepoCache, b *cache.BugCache, n NOTE_UNLOCKED, NOTE_MENTIONED_IN_ISSUE, NOTE_MENTIONED_IN_MERGE_REQUEST: + + reason := fmt.Sprintf("unsupported note type: %s", noteType.String()) + gi.out <- core.NewImportNothing("", reason) return nil default: @@ -337,10 +370,7 @@ func (gi *gitlabImporter) ensurePerson(repo *cache.RepoCache, id int) (*cache.Id return nil, err } - // importing a new identity - gi.importedIdentities++ - - return repo.NewIdentityRaw( + i, err = repo.NewIdentityRaw( user.Name, user.PublicEmail, user.Username, @@ -351,6 +381,12 @@ func (gi *gitlabImporter) ensurePerson(repo *cache.RepoCache, id int) (*cache.Id keyGitlabLogin: user.Username, }, ) + if err != nil { + return nil, err + } + + gi.out <- core.NewImportIdentity(i.Id()) + return i, nil } func parseID(id int) string { |