import.go

  1package launchpad
  2
  3import (
  4	"fmt"
  5	"time"
  6
  7	"github.com/MichaelMure/git-bug/bridge/core"
  8	"github.com/MichaelMure/git-bug/bug"
  9	"github.com/MichaelMure/git-bug/cache"
 10	"github.com/MichaelMure/git-bug/identity"
 11	"github.com/pkg/errors"
 12)
 13
 14type launchpadImporter struct {
 15	conf core.Configuration
 16}
 17
 18func (li *launchpadImporter) Init(conf core.Configuration) error {
 19	li.conf = conf
 20	return nil
 21}
 22
 23const keyLaunchpadID = "launchpad-id"
 24const keyLaunchpadLogin = "launchpad-login"
 25
 26func (li *launchpadImporter) makePerson(repo *cache.RepoCache, owner LPPerson) (*cache.IdentityCache, error) {
 27	// Look first in the cache
 28	i, err := repo.ResolveIdentityImmutableMetadata(keyLaunchpadLogin, owner.Login)
 29	if err == nil {
 30		return i, nil
 31	}
 32	if _, ok := err.(identity.ErrMultipleMatch); ok {
 33		return nil, err
 34	}
 35
 36	return repo.NewIdentityRaw(
 37		owner.Name,
 38		"",
 39		owner.Login,
 40		"",
 41		map[string]string{
 42			keyLaunchpadLogin: owner.Login,
 43		},
 44	)
 45}
 46
 47func (li *launchpadImporter) ImportAll(repo *cache.RepoCache) error {
 48	lpAPI := new(launchpadAPI)
 49
 50	err := lpAPI.Init()
 51	if err != nil {
 52		return err
 53	}
 54
 55	lpBugs, err := lpAPI.SearchTasks(li.conf["project"])
 56	if err != nil {
 57		return err
 58	}
 59
 60	for _, lpBug := range lpBugs {
 61		var b *cache.BugCache
 62		var err error
 63
 64		lpBugID := fmt.Sprintf("%d", lpBug.ID)
 65		b, err = repo.ResolveBugCreateMetadata(keyLaunchpadID, lpBugID)
 66		if err != nil && err != bug.ErrBugNotExist {
 67			return err
 68		}
 69
 70		owner, err := li.makePerson(repo, lpBug.Owner)
 71		if err != nil {
 72			return err
 73		}
 74
 75		if err == bug.ErrBugNotExist {
 76			createdAt, _ := time.Parse(time.RFC3339, lpBug.CreatedAt)
 77			b, err = repo.NewBugRaw(
 78				owner,
 79				createdAt.Unix(),
 80				lpBug.Title,
 81				lpBug.Description,
 82				nil,
 83				map[string]string{
 84					keyLaunchpadID: lpBugID,
 85				},
 86			)
 87			if err != nil {
 88				return errors.Wrapf(err, "failed to add bug id #%s", lpBugID)
 89			}
 90		} else {
 91			/* TODO: Update bug */
 92			fmt.Println("TODO: Update bug")
 93		}
 94
 95		/* Handle messages */
 96		if len(lpBug.Messages) == 0 {
 97			return errors.Wrapf(err, "failed to fetch comments for bug #%s", lpBugID)
 98		}
 99
100		// The Launchpad API returns the bug description as the first
101		// comment, so skip it.
102		for _, lpMessage := range lpBug.Messages[1:] {
103			_, err := b.ResolveTargetWithMetadata(keyLaunchpadID, lpMessage.ID)
104			if err != nil && err != cache.ErrNoMatchingOp {
105				return errors.Wrapf(err, "failed to fetch comments for bug #%s", lpBugID)
106			}
107
108			// If this comment already exists, we are probably
109			// updating an existing bug. We do not want to duplicate
110			// the comments, so let us just skip this one.
111			// TODO: Can Launchpad comments be edited?
112			if err == nil {
113				continue
114			}
115
116			owner, err := li.makePerson(repo, lpMessage.Owner)
117			if err != nil {
118				return err
119			}
120
121			// This is a new comment, we can add it.
122			createdAt, _ := time.Parse(time.RFC3339, lpMessage.CreatedAt)
123			err = b.AddCommentRaw(
124				owner,
125				createdAt.Unix(),
126				lpMessage.Content,
127				nil,
128				map[string]string{
129					keyLaunchpadID: lpMessage.ID,
130				})
131			if err != nil {
132				return errors.Wrapf(err, "failed to add comment to bug #%s", lpBugID)
133			}
134		}
135		err = b.CommitAsNeeded()
136		if err != nil {
137			return err
138		}
139	}
140	return nil
141}
142
143func (li *launchpadImporter) Import(repo *cache.RepoCache, id string) error {
144	fmt.Println("IMPORT")
145	return nil
146}