diff options
-rw-r--r-- | bridge/jira/client.go | 175 | ||||
-rw-r--r-- | bridge/jira/export.go | 79 | ||||
-rw-r--r-- | bridge/jira/import.go | 98 |
3 files changed, 154 insertions, 198 deletions
diff --git a/bridge/jira/client.go b/bridge/jira/client.go index 6ec1c9dd..15098a3c 100644 --- a/bridge/jira/client.go +++ b/bridge/jira/client.go @@ -315,21 +315,19 @@ type ClientTransport struct { } // RoundTrip overrides the default by adding the content-type header -func (self *ClientTransport) RoundTrip( - req *http.Request) (*http.Response, error) { +func (ct *ClientTransport) RoundTrip(req *http.Request) (*http.Response, error) { req.Header.Add("Content-Type", "application/json") - if self.basicAuthString != "" { + if ct.basicAuthString != "" { req.Header.Add("Authorization", - fmt.Sprintf("Basic %s", self.basicAuthString)) + fmt.Sprintf("Basic %s", ct.basicAuthString)) } - return self.underlyingTransport.RoundTrip(req) + return ct.underlyingTransport.RoundTrip(req) } -func (self *ClientTransport) SetCredentials( - username string, token string) { +func (ct *ClientTransport) SetCredentials(username string, token string) { credString := fmt.Sprintf("%s:%s", username, token) - self.basicAuthString = base64.StdEncoding.EncodeToString([]byte(credString)) + ct.basicAuthString = base64.StdEncoding.EncodeToString([]byte(credString)) } // Client Thin wrapper around the http.Client providing jira-specific methods @@ -490,8 +488,7 @@ func (client *Client) RefreshSessionTokenRaw(credentialsJSON []byte) error { // Search Perform an issue a JQL search on the /search endpoint // https://docs.atlassian.com/software/jira/docs/api/REST/8.2.6/#api/2/search -func (client *Client) Search(jql string, maxResults int, startAt int) ( - *SearchResult, error) { +func (client *Client) Search(jql string, maxResults int, startAt int) (*SearchResult, error) { url := fmt.Sprintf("%s/rest/api/2/search", client.serverURL) requestBody, err := json.Marshal(SearchRequest{ @@ -558,52 +555,51 @@ type SearchIterator struct { } // HasError returns true if the iterator is holding an error -func (self *SearchIterator) HasError() bool { - if self.Err == errDone { +func (si *SearchIterator) HasError() bool { + if si.Err == errDone { return false } - if self.Err == nil { + if si.Err == nil { return false } return true } // HasNext returns true if there is another item available in the result set -func (self *SearchIterator) HasNext() bool { - return self.Err == nil && self.itemIdx < len(self.searchResult.Issues) +func (si *SearchIterator) HasNext() bool { + return si.Err == nil && si.itemIdx < len(si.searchResult.Issues) } // Next Return the next item in the result set and advance the iterator. // Advancing the iterator may require fetching a new page. -func (self *SearchIterator) Next() *Issue { - if self.Err != nil { +func (si *SearchIterator) Next() *Issue { + if si.Err != nil { return nil } - issue := self.searchResult.Issues[self.itemIdx] - if self.itemIdx+1 < len(self.searchResult.Issues) { + issue := si.searchResult.Issues[si.itemIdx] + if si.itemIdx+1 < len(si.searchResult.Issues) { // We still have an item left in the currently cached page - self.itemIdx++ + si.itemIdx++ } else { - if self.searchResult.IsLastPage() { - self.Err = errDone + if si.searchResult.IsLastPage() { + si.Err = errDone } else { // There are still more pages to fetch, so fetch the next page and // cache it - self.searchResult, self.Err = self.client.Search( - self.jql, self.pageSize, self.searchResult.NextStartAt()) + si.searchResult, si.Err = si.client.Search( + si.jql, si.pageSize, si.searchResult.NextStartAt()) // NOTE(josh): we don't deal with the error now, we just cache it. // HasNext() will return false and the caller can check the error // afterward. - self.itemIdx = 0 + si.itemIdx = 0 } } return &issue } // IterSearch return an iterator over paginated results for a JQL search -func (client *Client) IterSearch( - jql string, pageSize int) *SearchIterator { +func (client *Client) IterSearch(jql string, pageSize int) *SearchIterator { result, err := client.Search(jql, pageSize, 0) iter := &SearchIterator{ @@ -620,9 +616,9 @@ func (client *Client) IterSearch( // GetIssue fetches an issue object via the /issue/{IssueIdOrKey} endpoint // https://docs.atlassian.com/software/jira/docs/api/REST/8.2.6/#api/2/issue -func (client *Client) GetIssue( - idOrKey string, fields []string, expand []string, +func (client *Client) GetIssue(idOrKey string, fields []string, expand []string, properties []string) (*Issue, error) { + url := fmt.Sprintf("%s/rest/api/2/issue/%s", client.serverURL, idOrKey) request, err := http.NewRequest("GET", url, nil) @@ -678,8 +674,7 @@ func (client *Client) GetIssue( // GetComments returns a page of comments via the issue/{IssueIdOrKey}/comment // endpoint // https://docs.atlassian.com/software/jira/docs/api/REST/8.2.6/#api/2/issue-getComment -func (client *Client) GetComments( - idOrKey string, maxResults int, startAt int) (*CommentPage, error) { +func (client *Client) GetComments(idOrKey string, maxResults int, startAt int) (*CommentPage, error) { url := fmt.Sprintf( "%s/rest/api/2/issue/%s/comment", client.serverURL, idOrKey) @@ -742,52 +737,51 @@ type CommentIterator struct { } // HasError returns true if the iterator is holding an error -func (self *CommentIterator) HasError() bool { - if self.Err == errDone { +func (ci *CommentIterator) HasError() bool { + if ci.Err == errDone { return false } - if self.Err == nil { + if ci.Err == nil { return false } return true } // HasNext returns true if there is another item available in the result set -func (self *CommentIterator) HasNext() bool { - return self.Err == nil && self.itemIdx < len(self.message.Comments) +func (ci *CommentIterator) HasNext() bool { + return ci.Err == nil && ci.itemIdx < len(ci.message.Comments) } // Next Return the next item in the result set and advance the iterator. // Advancing the iterator may require fetching a new page. -func (self *CommentIterator) Next() *Comment { - if self.Err != nil { +func (ci *CommentIterator) Next() *Comment { + if ci.Err != nil { return nil } - comment := self.message.Comments[self.itemIdx] - if self.itemIdx+1 < len(self.message.Comments) { + comment := ci.message.Comments[ci.itemIdx] + if ci.itemIdx+1 < len(ci.message.Comments) { // We still have an item left in the currently cached page - self.itemIdx++ + ci.itemIdx++ } else { - if self.message.IsLastPage() { - self.Err = errDone + if ci.message.IsLastPage() { + ci.Err = errDone } else { // There are still more pages to fetch, so fetch the next page and // cache it - self.message, self.Err = self.client.GetComments( - self.idOrKey, self.pageSize, self.message.NextStartAt()) + ci.message, ci.Err = ci.client.GetComments( + ci.idOrKey, ci.pageSize, ci.message.NextStartAt()) // NOTE(josh): we don't deal with the error now, we just cache it. // HasNext() will return false and the caller can check the error // afterward. - self.itemIdx = 0 + ci.itemIdx = 0 } } return &comment } // IterComments returns an iterator over paginated comments within an issue -func (client *Client) IterComments( - idOrKey string, pageSize int) *CommentIterator { +func (client *Client) IterComments(idOrKey string, pageSize int) *CommentIterator { message, err := client.GetComments(idOrKey, pageSize, 0) iter := &CommentIterator{ @@ -807,8 +801,7 @@ func (client *Client) IterComments( // /issue/{IssueIdOrKey} with (fields=*none&expand=changelog) // (for JIRA server) // https://docs.atlassian.com/software/jira/docs/api/REST/8.2.6/#api/2/issue -func (client *Client) GetChangeLog( - idOrKey string, maxResults int, startAt int) (*ChangeLogPage, error) { +func (client *Client) GetChangeLog(idOrKey string, maxResults int, startAt int) (*ChangeLogPage, error) { url := fmt.Sprintf( "%s/rest/api/2/issue/%s/changelog", client.serverURL, idOrKey) @@ -892,52 +885,51 @@ type ChangeLogIterator struct { } // HasError returns true if the iterator is holding an error -func (self *ChangeLogIterator) HasError() bool { - if self.Err == errDone { +func (cli *ChangeLogIterator) HasError() bool { + if cli.Err == errDone { return false } - if self.Err == nil { + if cli.Err == nil { return false } return true } // HasNext returns true if there is another item available in the result set -func (self *ChangeLogIterator) HasNext() bool { - return self.Err == nil && self.itemIdx < len(self.message.Entries) +func (cli *ChangeLogIterator) HasNext() bool { + return cli.Err == nil && cli.itemIdx < len(cli.message.Entries) } // Next Return the next item in the result set and advance the iterator. // Advancing the iterator may require fetching a new page. -func (self *ChangeLogIterator) Next() *ChangeLogEntry { - if self.Err != nil { +func (cli *ChangeLogIterator) Next() *ChangeLogEntry { + if cli.Err != nil { return nil } - item := self.message.Entries[self.itemIdx] - if self.itemIdx+1 < len(self.message.Entries) { + item := cli.message.Entries[cli.itemIdx] + if cli.itemIdx+1 < len(cli.message.Entries) { // We still have an item left in the currently cached page - self.itemIdx++ + cli.itemIdx++ } else { - if self.message.IsLastPage() { - self.Err = errDone + if cli.message.IsLastPage() { + cli.Err = errDone } else { // There are still more pages to fetch, so fetch the next page and // cache it - self.message, self.Err = self.client.GetChangeLog( - self.idOrKey, self.pageSize, self.message.NextStartAt()) + cli.message, cli.Err = cli.client.GetChangeLog( + cli.idOrKey, cli.pageSize, cli.message.NextStartAt()) // NOTE(josh): we don't deal with the error now, we just cache it. // HasNext() will return false and the caller can check the error // afterward. - self.itemIdx = 0 + cli.itemIdx = 0 } } return &item } // IterChangeLog returns an iterator over entries in the changelog for an issue -func (client *Client) IterChangeLog( - idOrKey string, pageSize int) *ChangeLogIterator { +func (client *Client) IterChangeLog(idOrKey string, pageSize int) *ChangeLogIterator { message, err := client.GetChangeLog(idOrKey, pageSize, 0) iter := &ChangeLogIterator{ @@ -994,9 +986,8 @@ func (client *Client) GetProject(projectIDOrKey string) (*Project, error) { } // CreateIssue creates a new JIRA issue and returns it -func (client *Client) CreateIssue( - projectIDOrKey, title, body string, extra map[string]interface{}) ( - *IssueCreateResult, error) { +func (client *Client) CreateIssue(projectIDOrKey, title, body string, + extra map[string]interface{}) (*IssueCreateResult, error) { url := fmt.Sprintf("%s/rest/api/2/issue", client.serverURL) @@ -1063,8 +1054,7 @@ func (client *Client) CreateIssue( } // UpdateIssueTitle changes the "summary" field of a JIRA issue -func (client *Client) UpdateIssueTitle( - issueKeyOrID, title string) (time.Time, error) { +func (client *Client) UpdateIssueTitle(issueKeyOrID, title string) (time.Time, error) { url := fmt.Sprintf( "%s/rest/api/2/issue/%s", client.serverURL, issueKeyOrID) @@ -1078,9 +1068,9 @@ func (client *Client) UpdateIssueTitle( } var buffer bytes.Buffer - fmt.Fprintf(&buffer, `{"update":{"summary":[`) - fmt.Fprintf(&buffer, `{"set":%s}`, data) - fmt.Fprintf(&buffer, `]}}`) + _, _ = fmt.Fprintf(&buffer, `{"update":{"summary":[`) + _, _ = fmt.Fprintf(&buffer, `{"set":%s}`, data) + _, _ = fmt.Fprintf(&buffer, `]}}`) data = buffer.Bytes() request, err := http.NewRequest("PUT", url, bytes.NewBuffer(data)) @@ -1119,8 +1109,7 @@ func (client *Client) UpdateIssueTitle( } // UpdateIssueBody changes the "description" field of a JIRA issue -func (client *Client) UpdateIssueBody( - issueKeyOrID, body string) (time.Time, error) { +func (client *Client) UpdateIssueBody(issueKeyOrID, body string) (time.Time, error) { url := fmt.Sprintf( "%s/rest/api/2/issue/%s", client.serverURL, issueKeyOrID) @@ -1133,9 +1122,9 @@ func (client *Client) UpdateIssueBody( } var buffer bytes.Buffer - fmt.Fprintf(&buffer, `{"update":{"description":[`) - fmt.Fprintf(&buffer, `{"set":%s}`, data) - fmt.Fprintf(&buffer, `]}}`) + _, _ = fmt.Fprintf(&buffer, `{"update":{"description":[`) + _, _ = fmt.Fprintf(&buffer, `{"set":%s}`, data) + _, _ = fmt.Fprintf(&buffer, `]}}`) data = buffer.Bytes() request, err := http.NewRequest("PUT", url, bytes.NewBuffer(data)) @@ -1279,8 +1268,7 @@ func (client *Client) UpdateComment(issueKeyOrID, commentID, body string) ( } // UpdateLabels changes labels for an issue -func (client *Client) UpdateLabels( - issueKeyOrID string, added, removed []bug.Label) (time.Time, error) { +func (client *Client) UpdateLabels(issueKeyOrID string, added, removed []bug.Label) (time.Time, error) { url := fmt.Sprintf( "%s/rest/api/2/issue/%s/", client.serverURL, issueKeyOrID) var responseTime time.Time @@ -1288,23 +1276,23 @@ func (client *Client) UpdateLabels( // NOTE(josh): Since updates are a list of heterogeneous objects let's just // manually build the JSON text var buffer bytes.Buffer - fmt.Fprintf(&buffer, `{"update":{"labels":[`) + _, _ = fmt.Fprintf(&buffer, `{"update":{"labels":[`) first := true for _, label := range added { if !first { - fmt.Fprintf(&buffer, ",") + _, _ = fmt.Fprintf(&buffer, ",") } - fmt.Fprintf(&buffer, `{"add":"%s"}`, label) + _, _ = fmt.Fprintf(&buffer, `{"add":"%s"}`, label) first = false } for _, label := range removed { if !first { - fmt.Fprintf(&buffer, ",") + _, _ = fmt.Fprintf(&buffer, ",") } - fmt.Fprintf(&buffer, `{"remove":"%s"}`, label) + _, _ = fmt.Fprintf(&buffer, `{"remove":"%s"}`, label) first = false } - fmt.Fprintf(&buffer, "]}}") + _, _ = fmt.Fprintf(&buffer, "]}}") data := buffer.Bytes() request, err := http.NewRequest("PUT", url, bytes.NewBuffer(data)) @@ -1349,8 +1337,7 @@ func (client *Client) UpdateLabels( } // GetTransitions returns a list of available transitions for an issue -func (client *Client) GetTransitions(issueKeyOrID string) ( - *TransitionList, error) { +func (client *Client) GetTransitions(issueKeyOrID string) (*TransitionList, error) { url := fmt.Sprintf( "%s/rest/api/2/issue/%s/transitions", client.serverURL, issueKeyOrID) @@ -1393,8 +1380,7 @@ func (client *Client) GetTransitions(issueKeyOrID string) ( return &message, nil } -func getTransitionTo( - tlist *TransitionList, desiredStateNameOrID string) *Transition { +func getTransitionTo(tlist *TransitionList, desiredStateNameOrID string) *Transition { for _, transition := range tlist.Transitions { if transition.To.ID == desiredStateNameOrID { return &transition @@ -1406,8 +1392,7 @@ func getTransitionTo( } // DoTransition changes the "status" of an issue -func (client *Client) DoTransition( - issueKeyOrID string, transitionID string) (time.Time, error) { +func (client *Client) DoTransition(issueKeyOrID string, transitionID string) (time.Time, error) { url := fmt.Sprintf( "%s/rest/api/2/issue/%s/transitions", client.serverURL, issueKeyOrID) var responseTime time.Time @@ -1417,7 +1402,7 @@ func (client *Client) DoTransition( // *compute* the necessary transitions and prompt for missing metatdata... // but that is complex var buffer bytes.Buffer - fmt.Fprintf(&buffer, + _, _ = fmt.Fprintf(&buffer, `{"transition":{"id":"%s"}, "resolution": {"name": "Done"}}`, transitionID) request, err := http.NewRequest("POST", url, bytes.NewBuffer(buffer.Bytes())) diff --git a/bridge/jira/export.go b/bridge/jira/export.go index f2b9d507..f329e490 100644 --- a/bridge/jira/export.go +++ b/bridge/jira/export.go @@ -43,47 +43,42 @@ type jiraExporter struct { } // Init . -func (self *jiraExporter) Init(repo *cache.RepoCache, - conf core.Configuration) error { - self.conf = conf - self.identityClient = make(map[entity.Id]*Client) - self.cachedOperationIDs = make(map[entity.Id]string) - self.cachedLabels = make(map[string]string) +func (je *jiraExporter) Init(repo *cache.RepoCache, conf core.Configuration) error { + je.conf = conf + je.identityClient = make(map[entity.Id]*Client) + je.cachedOperationIDs = make(map[entity.Id]string) + je.cachedLabels = make(map[string]string) return nil } // getIdentityClient return an API client configured with the credentials // of the given identity. If no client were found it will initialize it from // the known credentials map and cache it for next use -func (self *jiraExporter) getIdentityClient( - ctx context.Context, id entity.Id) (*Client, error) { - client, ok := self.identityClient[id] +func (je *jiraExporter) getIdentityClient(ctx context.Context, id entity.Id) (*Client, error) { + client, ok := je.identityClient[id] if ok { return client, nil } - client = NewClient(self.conf[keyServer], ctx) + client = NewClient(je.conf[keyServer], ctx) // NOTE: as a future enhancement, the bridge would ideally be able to generate // a separate session token for each user that we have stored credentials // for. However we currently only support a single user. - if id != self.userIdentity { + if id != je.userIdentity { return nil, ErrMissingCredentials } - err := client.Login(self.conf) + err := client.Login(je.conf) if err != nil { return nil, err } - self.identityClient[id] = client + je.identityClient[id] = client return client, nil } // ExportAll export all event made by the current user to Jira -func (self *jiraExporter) ExportAll( - ctx context.Context, repo *cache.RepoCache, since time.Time) ( - <-chan core.ExportResult, error) { - +func (je *jiraExporter) ExportAll(ctx context.Context, repo *cache.RepoCache, since time.Time) (<-chan core.ExportResult, error) { out := make(chan core.ExportResult) user, err := repo.GetUserIdentity() @@ -93,13 +88,13 @@ func (self *jiraExporter) ExportAll( // NOTE: this is currently only need to mock the credentials database in // getIdentityClient. - self.userIdentity = user.Id() - client, err := self.getIdentityClient(ctx, user.Id()) + je.userIdentity = user.Id() + client, err := je.getIdentityClient(ctx, user.Id()) if err != nil { return nil, err } - self.project, err = client.GetProject(self.conf[keyProject]) + je.project, err = client.GetProject(je.conf[keyProject]) if err != nil { return nil, err } @@ -108,7 +103,7 @@ func (self *jiraExporter) ExportAll( defer close(out) var allIdentitiesIds []entity.Id - for id := range self.identityClient { + for id := range je.identityClient { allIdentitiesIds = append(allIdentitiesIds, id) } @@ -139,7 +134,7 @@ func (self *jiraExporter) ExportAll( if snapshot.HasAnyActor(allIdentitiesIds...) { // try to export the bug and it associated events - err := self.exportBug(ctx, b, since, out) + err := je.exportBug(ctx, b, since, out) if err != nil { out <- core.NewExportError(errors.Wrap(err, "can't export bug"), id) return @@ -155,9 +150,7 @@ func (self *jiraExporter) ExportAll( } // exportBug publish bugs and related events -func (self *jiraExporter) exportBug( - ctx context.Context, b *cache.BugCache, since time.Time, - out chan<- core.ExportResult) error { +func (je *jiraExporter) exportBug(ctx context.Context, b *cache.BugCache, since time.Time, out chan<- core.ExportResult) error { snapshot := b.Snapshot() var bugJiraID string @@ -182,7 +175,7 @@ func (self *jiraExporter) exportBug( // skip bug if it is a jira bug but is associated with another project // (one bridge per JIRA project) project, ok := snapshot.GetCreateMetadata(keyJiraProject) - if ok && !stringInSlice(project, []string{self.project.ID, self.project.Key}) { + if ok && !stringInSlice(project, []string{je.project.ID, je.project.Key}) { out <- core.NewExportNothing( b.Id(), fmt.Sprintf("issue tagged with project: %s", project)) return nil @@ -195,7 +188,7 @@ func (self *jiraExporter) exportBug( bugJiraID = jiraID } else { // check that we have credentials for operation author - client, err := self.getIdentityClient(ctx, author.Id()) + client, err := je.getIdentityClient(ctx, author.Id()) if err != nil { // if bug is not yet exported and we do not have the author's credentials // then there is nothing we can do, so just skip this bug @@ -208,7 +201,7 @@ func (self *jiraExporter) exportBug( // Load any custom fields required to create an issue from the git // config file. fields := make(map[string]interface{}) - defaultFields, hasConf := self.conf[keyCreateDefaults] + defaultFields, hasConf := je.conf[keyCreateDefaults] if hasConf { err = json.Unmarshal([]byte(defaultFields), &fields) if err != nil { @@ -222,7 +215,7 @@ func (self *jiraExporter) exportBug( "id": "10001", } } - bugIDField, hasConf := self.conf[keyCreateGitBug] + bugIDField, hasConf := je.conf[keyCreateGitBug] if hasConf { // If the git configuration also indicates it, we can assign the git-bug // id to a custom field to assist in integrations @@ -231,7 +224,7 @@ func (self *jiraExporter) exportBug( // create bug result, err := client.CreateIssue( - self.project.ID, createOp.Title, createOp.Message, fields) + je.project.ID, createOp.Title, createOp.Message, fields) if err != nil { err := errors.Wrap(err, "exporting jira issue") out <- core.NewExportError(err, b.Id()) @@ -242,7 +235,7 @@ func (self *jiraExporter) exportBug( out <- core.NewExportBug(b.Id()) // mark bug creation operation as exported err = markOperationAsExported( - b, createOp.Id(), id, self.project.Key, time.Time{}) + b, createOp.Id(), id, je.project.Key, time.Time{}) if err != nil { err := errors.Wrap(err, "marking operation as exported") out <- core.NewExportError(err, b.Id()) @@ -262,10 +255,10 @@ func (self *jiraExporter) exportBug( } // cache operation jira id - self.cachedOperationIDs[createOp.Id()] = bugJiraID + je.cachedOperationIDs[createOp.Id()] = bugJiraID // lookup the mapping from git-bug "status" to JIRA "status" id - statusMap, err := getStatusMap(self.conf) + statusMap, err := getStatusMap(je.conf) if err != nil { return err } @@ -280,12 +273,12 @@ func (self *jiraExporter) exportBug( // cache the ID of already exported or imported issues and events from // Jira if id, ok := op.GetMetadata(keyJiraID); ok { - self.cachedOperationIDs[op.Id()] = id + je.cachedOperationIDs[op.Id()] = id continue } opAuthor := op.GetAuthor() - client, err := self.getIdentityClient(ctx, opAuthor.Id()) + client, err := je.getIdentityClient(ctx, opAuthor.Id()) if err != nil { out <- core.NewExportError( fmt.Errorf("missing operation author credentials for user %.8s", @@ -307,7 +300,7 @@ func (self *jiraExporter) exportBug( out <- core.NewExportComment(op.Id()) // cache comment id - self.cachedOperationIDs[op.Id()] = id + je.cachedOperationIDs[op.Id()] = id case *bug.EditCommentOperation: if opr.Target == createOp.Id() { @@ -325,7 +318,7 @@ func (self *jiraExporter) exportBug( // Otherwise it's an edit to an actual comment. A comment cannot be // edited before it was created, so it must be the case that we have // already observed and cached the AddCommentOperation. - commentID, ok := self.cachedOperationIDs[opr.Target] + commentID, ok := je.cachedOperationIDs[opr.Target] if !ok { // Since an edit has to come after the creation, we expect we would // have cached the creation id. @@ -392,7 +385,7 @@ func (self *jiraExporter) exportBug( // mark operation as exported err = markOperationAsExported( - b, op.Id(), id, self.project.Key, exportTime) + b, op.Id(), id, je.project.Key, exportTime) if err != nil { err := errors.Wrap(err, "marking operation as exported") out <- core.NewExportError(err, b.Id()) @@ -412,10 +405,7 @@ func (self *jiraExporter) exportBug( return nil } -func markOperationAsExported( - b *cache.BugCache, target entity.Id, jiraID, jiraProject string, - exportTime time.Time) error { - +func markOperationAsExported(b *cache.BugCache, target entity.Id, jiraID, jiraProject string, exportTime time.Time) error { newMetadata := map[string]string{ keyJiraID: jiraID, keyJiraProject: jiraProject, @@ -431,10 +421,7 @@ func markOperationAsExported( // UpdateIssueStatus attempts to change the "status" field by finding a // transition which achieves the desired state and then performing that // transition -func UpdateIssueStatus( - client *Client, issueKeyOrID string, desiredStateNameOrID string) ( - time.Time, error) { - +func UpdateIssueStatus(client *Client, issueKeyOrID string, desiredStateNameOrID string) (time.Time, error) { var responseTime time.Time tlist, err := client.GetTransitions(issueKeyOrID) diff --git a/bridge/jira/import.go b/bridge/jira/import.go index bc1bf428..6a755a36 100644 --- a/bridge/jira/import.go +++ b/bridge/jira/import.go @@ -35,31 +35,27 @@ type jiraImporter struct { } // Init . -func (gi *jiraImporter) Init(repo *cache.RepoCache, - conf core.Configuration) error { - gi.conf = conf +func (ji *jiraImporter) Init(repo *cache.RepoCache, conf core.Configuration) error { + ji.conf = conf return nil } // ImportAll iterate over all the configured repository issues and ensure the // creation of the missing issues / timeline items / edits / label events ... -func (self *jiraImporter) ImportAll( - ctx context.Context, repo *cache.RepoCache, since time.Time) ( - <-chan core.ImportResult, error) { - +func (ji *jiraImporter) ImportAll(ctx context.Context, repo *cache.RepoCache, since time.Time) (<-chan core.ImportResult, error) { sinceStr := since.Format("2006-01-02 15:04") - serverURL := self.conf[keyServer] - project := self.conf[keyProject] + serverURL := ji.conf[keyServer] + project := ji.conf[keyProject] // TODO(josh)[da52062]: Validate token and if it is expired then prompt for // credentials and generate a new one out := make(chan core.ImportResult) - self.out = out + ji.out = out go func() { - defer close(self.out) + defer close(ji.out) client := NewClient(serverURL, ctx) - err := client.Login(self.conf) + err := client.Login(ji.conf) if err != nil { out <- core.NewImportError(err, "") return @@ -79,7 +75,7 @@ func (self *jiraImporter) ImportAll( for searchIter = client.IterSearch(jql, defaultPageSize); searchIter.HasNext(); { issue := searchIter.Next() - bug, err := self.ensureIssue(repo, *issue) + b, err := ji.ensureIssue(repo, *issue) if err != nil { err := fmt.Errorf("issue creation: %v", err) out <- core.NewImportError(err, "") @@ -90,7 +86,7 @@ func (self *jiraImporter) ImportAll( for commentIter = client.IterComments(issue.ID, defaultPageSize); commentIter.HasNext(); { comment := commentIter.Next() - err := self.ensureComment(repo, bug, *comment) + err := ji.ensureComment(repo, b, *comment) if err != nil { out <- core.NewImportError(err, "") } @@ -99,7 +95,7 @@ func (self *jiraImporter) ImportAll( out <- core.NewImportError(commentIter.Err, "") } - snapshot := bug.Snapshot() + snapshot := b.Snapshot() opIdx := 0 var changelogIter *ChangeLogIterator @@ -127,10 +123,9 @@ func (self *jiraImporter) ImportAll( } } if opIdx < len(snapshot.Operations) { - err = self.ensureChange( - repo, bug, *changelogEntry, snapshot.Operations[opIdx]) + err = ji.ensureChange(repo, b, *changelogEntry, snapshot.Operations[opIdx]) } else { - err = self.ensureChange(repo, bug, *changelogEntry, nil) + err = ji.ensureChange(repo, b, *changelogEntry, nil) } if err != nil { out <- core.NewImportError(err, "") @@ -141,9 +136,9 @@ func (self *jiraImporter) ImportAll( out <- core.NewImportError(changelogIter.Err, "") } - if !bug.NeedCommit() { - out <- core.NewImportNothing(bug.Id(), "no imported operation") - } else if err := bug.Commit(); err != nil { + if !b.NeedCommit() { + out <- core.NewImportNothing(b.Id(), "no imported operation") + } else if err := b.Commit(); err != nil { err = fmt.Errorf("bug commit: %v", err) out <- core.NewImportError(err, "") return @@ -158,9 +153,7 @@ func (self *jiraImporter) ImportAll( } // Create a bug.Person from a JIRA user -func (self *jiraImporter) ensurePerson( - repo *cache.RepoCache, user User) (*cache.IdentityCache, error) { - +func (ji *jiraImporter) ensurePerson(repo *cache.RepoCache, user User) (*cache.IdentityCache, error) { // Look first in the cache i, err := repo.ResolveIdentityImmutableMetadata( keyJiraUser, string(user.Key)) @@ -184,14 +177,13 @@ func (self *jiraImporter) ensurePerson( return nil, err } - self.out <- core.NewImportIdentity(i.Id()) + ji.out <- core.NewImportIdentity(i.Id()) return i, nil } // Create a bug.Bug based from a JIRA issue -func (self *jiraImporter) ensureIssue( - repo *cache.RepoCache, issue Issue) (*cache.BugCache, error) { - author, err := self.ensurePerson(repo, issue.Fields.Creator) +func (ji *jiraImporter) ensureIssue(repo *cache.RepoCache, issue Issue) (*cache.BugCache, error) { + author, err := ji.ensurePerson(repo, issue.Fields.Creator) if err != nil { return nil, err } @@ -220,13 +212,13 @@ func (self *jiraImporter) ensureIssue( core.MetaKeyOrigin: target, keyJiraID: issue.ID, keyJiraKey: issue.Key, - keyJiraProject: self.conf[keyProject], + keyJiraProject: ji.conf[keyProject], }) if err != nil { return nil, err } - self.out <- core.NewImportBug(b.Id()) + ji.out <- core.NewImportBug(b.Id()) } return b, nil @@ -238,10 +230,9 @@ func getTimeDerivedID(jiraID string, timestamp MyTime) string { } // Create a bug.Comment from a JIRA comment -func (self *jiraImporter) ensureComment(repo *cache.RepoCache, - b *cache.BugCache, item Comment) error { +func (ji *jiraImporter) ensureComment(repo *cache.RepoCache, b *cache.BugCache, item Comment) error { // ensure person - author, err := self.ensurePerson(repo, item.Author) + author, err := ji.ensurePerson(repo, item.Author) if err != nil { return err } @@ -279,7 +270,7 @@ func (self *jiraImporter) ensureComment(repo *cache.RepoCache, return err } - self.out <- core.NewImportComment(op.Id()) + ji.out <- core.NewImportComment(op.Id()) targetOpID = op.Id() } @@ -293,8 +284,7 @@ func (self *jiraImporter) ensureComment(repo *cache.RepoCache, // timestamp. Note that this must be consistent with the exporter during // export of an EditCommentOperation derivedID := getTimeDerivedID(item.ID, item.Updated) - _, err = b.ResolveOperationWithMetadata( - keyJiraID, derivedID) + _, err = b.ResolveOperationWithMetadata(keyJiraID, derivedID) if err == nil { // Already imported this edition return nil @@ -305,7 +295,7 @@ func (self *jiraImporter) ensureComment(repo *cache.RepoCache, } // ensure editor identity - editor, err := self.ensurePerson(repo, item.UpdateAuthor) + editor, err := ji.ensurePerson(repo, item.UpdateAuthor) if err != nil { return err } @@ -329,7 +319,7 @@ func (self *jiraImporter) ensureComment(repo *cache.RepoCache, return err } - self.out <- core.NewImportCommentEdition(op.Id()) + ji.out <- core.NewImportCommentEdition(op.Id()) return nil } @@ -363,9 +353,7 @@ func labelSetsMatch(jiraSet []string, gitbugSet []bug.Label) bool { // Create a bug.Operation (or a series of operations) from a JIRA changelog // entry -func (self *jiraImporter) ensureChange( - repo *cache.RepoCache, b *cache.BugCache, entry ChangeLogEntry, - potentialOp bug.Operation) error { +func (ji *jiraImporter) ensureChange(repo *cache.RepoCache, b *cache.BugCache, entry ChangeLogEntry, potentialOp bug.Operation) error { // If we have an operation which is already mapped to the entire changelog // entry then that means this changelog entry was induced by an export @@ -383,7 +371,7 @@ func (self *jiraImporter) ensureChange( // I don't thing git-bug has a single operation to modify an arbitrary // number of fields in one go, so we break up the single JIRA changelog // entry into individual field updates. - author, err := self.ensurePerson(repo, entry.Author) + author, err := ji.ensurePerson(repo, entry.Author) if err != nil { return err } @@ -392,7 +380,7 @@ func (self *jiraImporter) ensureChange( return fmt.Errorf("Received changelog entry with no item! (%s)", entry.ID) } - statusMap, err := getStatusMapReverse(self.conf) + statusMap, err := getStatusMapReverse(ji.conf) if err != nil { return err } @@ -407,13 +395,10 @@ func (self *jiraImporter) ensureChange( case "labels": fromLabels := removeEmpty(strings.Split(item.FromString, " ")) toLabels := removeEmpty(strings.Split(item.ToString, " ")) - removedLabels, addedLabels, _ := setSymmetricDifference( - fromLabels, toLabels) + removedLabels, addedLabels, _ := setSymmetricDifference(fromLabels, toLabels) opr, isRightType := potentialOp.(*bug.LabelChangeOperation) - if isRightType && - labelSetsMatch(addedLabels, opr.Added) && - labelSetsMatch(removedLabels, opr.Removed) { + if isRightType && labelSetsMatch(addedLabels, opr.Added) && labelSetsMatch(removedLabels, opr.Removed) { _, err := b.SetMetadata(opr.Id(), map[string]string{ keyJiraOperationID: entry.ID, }) @@ -484,8 +469,7 @@ func (self *jiraImporter) ensureChange( case "labels": fromLabels := removeEmpty(strings.Split(item.FromString, " ")) toLabels := removeEmpty(strings.Split(item.ToString, " ")) - removedLabels, addedLabels, _ := setSymmetricDifference( - fromLabels, toLabels) + removedLabels, addedLabels, _ := setSymmetricDifference(fromLabels, toLabels) op, err := b.ForceChangeLabelsRaw( author, @@ -501,7 +485,7 @@ func (self *jiraImporter) ensureChange( return err } - self.out <- core.NewImportLabelChange(op.Id()) + ji.out <- core.NewImportLabelChange(op.Id()) case "status": statusStr, hasMap := statusMap[item.To] @@ -519,7 +503,7 @@ func (self *jiraImporter) ensureChange( if err != nil { return err } - self.out <- core.NewImportStatusChange(op.Id()) + ji.out <- core.NewImportStatusChange(op.Id()) case bug.ClosedStatus.String(): op, err := b.CloseRaw( @@ -533,10 +517,10 @@ func (self *jiraImporter) ensureChange( if err != nil { return err } - self.out <- core.NewImportStatusChange(op.Id()) + ji.out <- core.NewImportStatusChange(op.Id()) } } else { - self.out <- core.NewImportError( + ji.out <- core.NewImportError( fmt.Errorf( "No git-bug status mapped for jira status %s (%s)", item.ToString, item.To), "") @@ -558,7 +542,7 @@ func (self *jiraImporter) ensureChange( return err } - self.out <- core.NewImportTitleEdition(op.Id()) + ji.out <- core.NewImportTitleEdition(op.Id()) case "description": // NOTE(josh): JIRA calls it "description", which sounds more like the @@ -576,10 +560,10 @@ func (self *jiraImporter) ensureChange( return err } - self.out <- core.NewImportCommentEdition(op.Id()) + ji.out <- core.NewImportCommentEdition(op.Id()) default: - self.out <- core.NewImportWarning( + ji.out <- core.NewImportWarning( fmt.Errorf( "Unhandled changelog event %s", item.Field), "") } |