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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
= Remote bugs linking back to Launchpad =
Some bug trackers support linking back to bugs in Launchpad. This way we
can tell external bug trackers that we're watching the bug, and make it
easier to users of the external bug tracker to get more information
about the bug.
>>> from zope.interface import implements
>>> from lp.bugs.tests.externalbugtracker import (
... TestExternalBugTracker)
>>> from lp.bugs.interfaces.externalbugtracker import (
... ISupportsBackLinking)
>>> class BackLinkingExternalBugTracker(TestExternalBugTracker):
... implements(ISupportsBackLinking)
...
... def __init__(self, baseurl):
... super(BackLinkingExternalBugTracker, self).__init__(baseurl)
... self.last_launchpad_bug_id = None
...
... def getLaunchpadBugId(self, remote_bug):
... print "Getting Launchpad id for bug %s" % remote_bug
... return self.last_launchpad_bug_id
...
... def setLaunchpadBugId(self, remote_bug, launchpad_bug_id,
... launchpad_bug_url):
... self.last_launchpad_bug_id = launchpad_bug_id
... print "Setting Launchpad id for bug %s" % remote_bug
The methods are called by the CheckwatchesMaster class:
>>> from lp.testing.layers import LaunchpadZopelessLayer
>>> txn = transaction
>>> LaunchpadZopelessLayer.switchDbUser('launchpad')
>>> bug_watch = factory.makeBugWatch('42')
>>> bug_watch.bug.default_bugtask.bugwatch = bug_watch
>>> bug_watch_2 = factory.makeBugWatch('42', bug_watch.bugtracker)
>>> bug_watch_2.bug.default_bugtask.bugwatch = bug_watch_2
>>> bug_watch_without_bugtask = (
... factory.makeBugWatch('42', bug_watch.bugtracker))
>>> unlinked_bug = factory.makeBug()
>>> txn.commit()
>>> LaunchpadZopelessLayer.switchDbUser('checkwatches')
>>> from lp.bugs.scripts.checkwatches import CheckwatchesMaster
>>> checkwatches_master = CheckwatchesMaster(txn)
>>> txn.commit()
>>> external_bugtracker = BackLinkingExternalBugTracker(
... 'http://example.com/')
>>> checkwatches_master.updateBugWatches(external_bugtracker, [bug_watch])
Getting Launchpad id for bug 42
Setting Launchpad id for bug 42
>>> external_bugtracker.last_launchpad_bug_id == bug_watch.bug.id
True
For comment syncing and back-linking to be attempted, bug watches must
be related to a bug task, not just a bug.
>>> checkwatches_master.updateBugWatches(
... external_bugtracker, [bug_watch_without_bugtask])
== BugWatchUpdater.linkLaunchpadBug() ==
The BugWatchUpdater method that does the work of setting the Launchpad
bug link is linkLaunchpadBug(). This method first retrieves the
current Launchpad bug ID for the remote bug. If the remote bug is
already linked to a Launchpad bug other than the one that we're trying
to link it to, the BugWatchUpdater will check that the bug that is
already linked has a valid watch on the remote bug in question. If it
does, the link will remain unchanged. Otherwise it will be updated.
Bug 42 on the remote bug tracker is linked to using bug_watch.
>>> external_bugtracker.last_launchpad_bug_id == bug_watch.bug.id
True
Trying to link another bug to it will have no effect since the bug that
is currently linked has a valid bug watch. Only getLaunchpadBugId() will
be called on our BackLinkingExternalBugTracker.
>>> bug_watch.bug.id == bug_watch_2.bug.id
False
>>> transaction.commit()
>>> from lp.bugs.scripts.checkwatches.core import CheckwatchesMaster
>>> from lp.bugs.scripts.checkwatches.tests.test_bugwatchupdater import (
... make_bug_watch_updater)
>>> bug_watch_updater = make_bug_watch_updater(
... CheckwatchesMaster(transaction), bug_watch,
... external_bugtracker)
>>> bug_watch_updater.linkLaunchpadBug()
Getting Launchpad id for bug 42
However, if we set the current Launchpad bug ID on our
BackLinkingExternalBugTracker to a Launchpad bug that doesn't link to
the remote bug, BugWatchUpdater.linkLaunchpadBug() will call
getLaunchpadBugId() and then, when it discovers that the current
Launchpad bug ID isn't valid, setLaunchpadBugId() to correct the error.
unlinked_bug doesn't link to bug 42 on the remote bug tracker.
>>> print unlinked_bug.getBugWatch(
... bug_watch.bugtracker, bug_watch.remotebug)
None
However, the remote bug currently thinks that unlinked_bug does in
fact link to it.
>>> external_bugtracker.last_launchpad_bug_id = unlinked_bug.id
Calling linkLaunchpadBug() with a bug watch that actually does link to
bug 42 will correct the error.
>>> transaction.commit()
>>> bug_watch_updater.linkLaunchpadBug()
Getting Launchpad id for bug 42
Setting Launchpad id for bug 42
linkLaunchpadBug() will also handle cases where the current Launchpad
bug ID for a remote bug references a Launchpad bug that doesn't exist.
The remote bug's Launchpad bug ID will be overwritten to correct the
error.
>>> external_bugtracker.last_launchpad_bug_id = 0
>>> bug_watch_updater.linkLaunchpadBug()
Getting Launchpad id for bug 42
Setting Launchpad id for bug 42
|