Merge lp:~thumper/launchpad/deleting-individual-branch-revisions into lp:launchpad
- deleting-individual-branch-revisions
- Merge into devel
Proposed by
Tim Penhey
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Paul Hummer | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 11534 | ||||
Proposed branch: | lp:~thumper/launchpad/deleting-individual-branch-revisions | ||||
Merge into: | lp:launchpad | ||||
Diff against target: |
443 lines (+109/-88) 10 files modified
lib/canonical/config/schema-lazr.conf (+1/-0) lib/lp/code/configure.zcml (+0/-11) lib/lp/code/doc/revision.txt (+5/-18) lib/lp/code/interfaces/branch.py (+6/-0) lib/lp/code/interfaces/branchrevision.py (+3/-8) lib/lp/code/model/branch.py (+13/-9) lib/lp/code/model/branchrevision.py (+4/-18) lib/lp/code/model/tests/test_branch.py (+56/-2) lib/lp/codehosting/scanner/bzrsync.py (+20/-17) lib/lp/codehosting/scanner/tests/test_bzrsync.py (+1/-5) |
||||
To merge this branch: | bzr merge lp:~thumper/launchpad/deleting-individual-branch-revisions | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Paul Hummer (community) | Approve | ||
Review via email: mp+34943@code.launchpad.net |
Commit message
Stop deleting branch revision objects by their ids.
Description of the change
This is a pre-branch branch.
The work coming is to remove the BranchRevision.id column. In order to do this we need to update the code that is currently using it.
The only place it is really used is in the branch scanner where it is used to remove BranchRevision rows for revisions that are no longer in the ancestry of a branch due to `push --overwrite`.
The way to delete branch revision objects has been moved onto the branch object itself, and it now handles deleting multiple branch revisions at once.
To post a comment you must log in.
Revision history for this message
Tim Penhey (thumper) wrote : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/canonical/config/schema-lazr.conf' | |||
2 | --- lib/canonical/config/schema-lazr.conf 2010-08-30 00:51:55 +0000 | |||
3 | +++ lib/canonical/config/schema-lazr.conf 2010-09-09 20:24:49 +0000 | |||
4 | @@ -41,6 +41,7 @@ | |||
5 | 41 | 41 | ||
6 | 42 | 42 | ||
7 | 43 | [branchscanner] | 43 | [branchscanner] |
8 | 44 | branch_revision_delete_count: 100 | ||
9 | 44 | # The database user which will be used by this process. | 45 | # The database user which will be used by this process. |
10 | 45 | # datatype: string | 46 | # datatype: string |
11 | 46 | dbuser: branchscanner | 47 | dbuser: branchscanner |
12 | 47 | 48 | ||
13 | === modified file 'lib/lp/code/configure.zcml' | |||
14 | --- lib/lp/code/configure.zcml 2010-09-01 20:59:44 +0000 | |||
15 | +++ lib/lp/code/configure.zcml 2010-09-09 20:24:49 +0000 | |||
16 | @@ -642,17 +642,6 @@ | |||
17 | 642 | <allow interface="lp.code.interfaces.branchrevision.IBranchRevision"/> | 642 | <allow interface="lp.code.interfaces.branchrevision.IBranchRevision"/> |
18 | 643 | </class> | 643 | </class> |
19 | 644 | 644 | ||
20 | 645 | <!-- BranchRevisionSet --> | ||
21 | 646 | |||
22 | 647 | <class class="lp.code.model.branchrevision.BranchRevisionSet"> | ||
23 | 648 | <allow interface="lp.code.interfaces.branchrevision.IBranchRevisionSet"/> | ||
24 | 649 | </class> | ||
25 | 650 | <securedutility | ||
26 | 651 | class="lp.code.model.branchrevision.BranchRevisionSet" | ||
27 | 652 | provides="lp.code.interfaces.branchrevision.IBranchRevisionSet"> | ||
28 | 653 | <allow interface="lp.code.interfaces.branchrevision.IBranchRevisionSet"/> | ||
29 | 654 | </securedutility> | ||
30 | 655 | |||
31 | 656 | <!-- CodeReviewComment --> | 645 | <!-- CodeReviewComment --> |
32 | 657 | 646 | ||
33 | 658 | <class class="lp.code.model.codereviewcomment.CodeReviewComment"> | 647 | <class class="lp.code.model.codereviewcomment.CodeReviewComment"> |
34 | 659 | 648 | ||
35 | === modified file 'lib/lp/code/doc/revision.txt' | |||
36 | --- lib/lp/code/doc/revision.txt 2010-07-14 14:50:58 +0000 | |||
37 | +++ lib/lp/code/doc/revision.txt 2010-09-09 20:24:49 +0000 | |||
38 | @@ -130,7 +130,7 @@ | |||
39 | 130 | In particular, IBranch.getScannerData efficiently retrieves the BranchRevision | 130 | In particular, IBranch.getScannerData efficiently retrieves the BranchRevision |
40 | 131 | data needed by the branch-scanner script. | 131 | data needed by the branch-scanner script. |
41 | 132 | 132 | ||
43 | 133 | >>> ancestry, history, mapping = branch.getScannerData() | 133 | >>> ancestry, history = branch.getScannerData() |
44 | 134 | 134 | ||
45 | 135 | The first return value is a set of revision_id strings for the full ancestry | 135 | The first return value is a set of revision_id strings for the full ancestry |
46 | 136 | of the branch. | 136 | of the branch. |
47 | @@ -158,19 +158,6 @@ | |||
48 | 158 | foo@localhost-20051031170239-5fce7d6bd3f01efc | 158 | foo@localhost-20051031170239-5fce7d6bd3f01efc |
49 | 159 | foo@localhost-20051031170357-1301ad6d387feb23 | 159 | foo@localhost-20051031170357-1301ad6d387feb23 |
50 | 160 | 160 | ||
51 | 161 | The third return value is a mapping from revision_id strings to database ids | ||
52 | 162 | integers of the corresponding BranchRevision rows for this branch. | ||
53 | 163 | |||
54 | 164 | >>> for revision_id, db_id in sorted(mapping.iteritems()): | ||
55 | 165 | ... print revision_id, db_id | ||
56 | 166 | foo@localhost-20051031165758-48acedf2b6a2e898 12 | ||
57 | 167 | foo@localhost-20051031170008-098959758bf79803 13 | ||
58 | 168 | foo@localhost-20051031170239-5fce7d6bd3f01efc 14 | ||
59 | 169 | foo@localhost-20051031170357-1301ad6d387feb23 15 | ||
60 | 170 | test@canonical.com-20051031165248-6f1bb97973c2b4f4 10 | ||
61 | 171 | test@canonical.com-20051031165338-5f2f3d6b10bb3bf0 11 | ||
62 | 172 | test@canonical.com-20051031165532-3113df343e494daa 18 | ||
63 | 173 | test@canonical.com-20051031165901-43b9644ec2eacc4e 19 | ||
64 | 174 | 161 | ||
65 | 175 | === Deleting BranchRevisions === | 162 | === Deleting BranchRevisions === |
66 | 176 | 163 | ||
67 | @@ -180,7 +167,7 @@ | |||
68 | 180 | of the branch, then some of BranchRevision records will need to be | 167 | of the branch, then some of BranchRevision records will need to be |
69 | 181 | removed. | 168 | removed. |
70 | 182 | 169 | ||
72 | 183 | BranchRevision records are deleted using the `BranchRevisionSet.delete` | 170 | BranchRevision records are deleted using the `Branch.removeBranchRevisions` |
73 | 184 | method. | 171 | method. |
74 | 185 | 172 | ||
75 | 186 | 173 | ||
76 | @@ -197,14 +184,14 @@ | |||
77 | 197 | 6 | 184 | 6 |
78 | 198 | >>> revno_6.branch == branch | 185 | >>> revno_6.branch == branch |
79 | 199 | True | 186 | True |
81 | 200 | >>> print revno_6.revision.revision_id | 187 | >>> rev_id = revno_6.revision.revision_id |
82 | 188 | >>> print rev_id | ||
83 | 201 | foo@localhost-20051031170357-1301ad6d387feb23 | 189 | foo@localhost-20051031170357-1301ad6d387feb23 |
84 | 202 | 190 | ||
85 | 203 | We remove the last revision from the branch. This is similar to what | 191 | We remove the last revision from the branch. This is similar to what |
86 | 204 | "bzr uncommit" does. | 192 | "bzr uncommit" does. |
87 | 205 | 193 | ||
90 | 206 | >>> from lp.code.interfaces.branchrevision import IBranchRevisionSet | 194 | >>> branch.removeBranchRevisions(rev_id) |
89 | 207 | >>> getUtility(IBranchRevisionSet).delete(revno_6.id) | ||
91 | 208 | 195 | ||
92 | 209 | Afterwards, the last commit on the branch has revision number 5. | 196 | Afterwards, the last commit on the branch has revision number 5. |
93 | 210 | 197 | ||
94 | 211 | 198 | ||
95 | === modified file 'lib/lp/code/interfaces/branch.py' | |||
96 | --- lib/lp/code/interfaces/branch.py 2010-09-03 11:54:23 +0000 | |||
97 | +++ lib/lp/code/interfaces/branch.py 2010-09-09 20:24:49 +0000 | |||
98 | @@ -803,6 +803,12 @@ | |||
99 | 803 | def createBranchRevision(sequence, revision): | 803 | def createBranchRevision(sequence, revision): |
100 | 804 | """Create a new `BranchRevision` for this branch.""" | 804 | """Create a new `BranchRevision` for this branch.""" |
101 | 805 | 805 | ||
102 | 806 | def removeBranchRevisions(revision_ids): | ||
103 | 807 | """Remove the specified revision_ids from this Branch's revisions. | ||
104 | 808 | |||
105 | 809 | :param revision_ids: Either a single revision_id or an iterable. | ||
106 | 810 | """ | ||
107 | 811 | |||
108 | 806 | def createBranchRevisionFromIDs(revision_id_sequence_pairs): | 812 | def createBranchRevisionFromIDs(revision_id_sequence_pairs): |
109 | 807 | """Create a batch of BranchRevision objects. | 813 | """Create a batch of BranchRevision objects. |
110 | 808 | 814 | ||
111 | 809 | 815 | ||
112 | === modified file 'lib/lp/code/interfaces/branchrevision.py' | |||
113 | --- lib/lp/code/interfaces/branchrevision.py 2010-08-20 20:31:18 +0000 | |||
114 | +++ lib/lp/code/interfaces/branchrevision.py 2010-09-09 20:24:49 +0000 | |||
115 | @@ -6,7 +6,9 @@ | |||
116 | 6 | """BranchRevision interfaces.""" | 6 | """BranchRevision interfaces.""" |
117 | 7 | 7 | ||
118 | 8 | __metaclass__ = type | 8 | __metaclass__ = type |
120 | 9 | __all__ = ['IBranchRevision', 'IBranchRevisionSet'] | 9 | __all__ = [ |
121 | 10 | 'IBranchRevision', | ||
122 | 11 | ] | ||
123 | 10 | 12 | ||
124 | 11 | from zope.interface import ( | 13 | from zope.interface import ( |
125 | 12 | Attribute, | 14 | Attribute, |
126 | @@ -32,10 +34,3 @@ | |||
127 | 32 | " None for merged revisions which are not part of the history.")) | 34 | " None for merged revisions which are not part of the history.")) |
128 | 33 | branch = Attribute("The branch this revision is included in.") | 35 | branch = Attribute("The branch this revision is included in.") |
129 | 34 | revision = Attribute("A revision that is included in the branch.") | 36 | revision = Attribute("A revision that is included in the branch.") |
130 | 35 | |||
131 | 36 | |||
132 | 37 | class IBranchRevisionSet(Interface): | ||
133 | 38 | """The set of all branch-revision associations.""" | ||
134 | 39 | |||
135 | 40 | def delete(branch_revision_id): | ||
136 | 41 | """Delete the BranchRevision.""" | ||
137 | 42 | 37 | ||
138 | === modified file 'lib/lp/code/model/branch.py' | |||
139 | --- lib/lp/code/model/branch.py 2010-09-03 11:54:23 +0000 | |||
140 | +++ lib/lp/code/model/branch.py 2010-09-09 20:24:49 +0000 | |||
141 | @@ -26,7 +26,6 @@ | |||
142 | 26 | And, | 26 | And, |
143 | 27 | Count, | 27 | Count, |
144 | 28 | Desc, | 28 | Desc, |
145 | 29 | Max, | ||
146 | 30 | NamedFunc, | 29 | NamedFunc, |
147 | 31 | Not, | 30 | Not, |
148 | 32 | Or, | 31 | Or, |
149 | @@ -58,12 +57,8 @@ | |||
150 | 58 | ILaunchpadCelebrities, | 57 | ILaunchpadCelebrities, |
151 | 59 | IPrivacy, | 58 | IPrivacy, |
152 | 60 | ) | 59 | ) |
153 | 60 | from canonical.launchpad.interfaces.lpstorm import IMasterStore | ||
154 | 61 | from canonical.launchpad.webapp import urlappend | 61 | from canonical.launchpad.webapp import urlappend |
155 | 62 | from canonical.launchpad.webapp.interfaces import ( | ||
156 | 63 | IStoreSelector, | ||
157 | 64 | MAIN_STORE, | ||
158 | 65 | SLAVE_FLAVOR, | ||
159 | 66 | ) | ||
160 | 67 | from lp.app.errors import UserCannotUnsubscribePerson | 62 | from lp.app.errors import UserCannotUnsubscribePerson |
161 | 68 | from lp.buildmaster.model.buildqueue import BuildQueue | 63 | from lp.buildmaster.model.buildqueue import BuildQueue |
162 | 69 | from lp.code.bzr import ( | 64 | from lp.code.bzr import ( |
163 | @@ -804,6 +799,17 @@ | |||
164 | 804 | BranchRevision.branch == self, | 799 | BranchRevision.branch == self, |
165 | 805 | query).one() | 800 | query).one() |
166 | 806 | 801 | ||
167 | 802 | def removeBranchRevisions(self, revision_ids): | ||
168 | 803 | """See `IBranch`.""" | ||
169 | 804 | if isinstance(revision_ids, basestring): | ||
170 | 805 | revision_ids = [revision_ids] | ||
171 | 806 | IMasterStore(BranchRevision).find( | ||
172 | 807 | BranchRevision, | ||
173 | 808 | BranchRevision.branch == self, | ||
174 | 809 | BranchRevision.revision_id.is_in( | ||
175 | 810 | Select(Revision.id, | ||
176 | 811 | Revision.revision_id.is_in(revision_ids)))).remove() | ||
177 | 812 | |||
178 | 807 | def createBranchRevision(self, sequence, revision): | 813 | def createBranchRevision(self, sequence, revision): |
179 | 808 | """See `IBranch`.""" | 814 | """See `IBranch`.""" |
180 | 809 | branch_revision = BranchRevision( | 815 | branch_revision = BranchRevision( |
181 | @@ -921,13 +927,11 @@ | |||
182 | 921 | rows = rows.order_by(BranchRevision.sequence) | 927 | rows = rows.order_by(BranchRevision.sequence) |
183 | 922 | ancestry = set() | 928 | ancestry = set() |
184 | 923 | history = [] | 929 | history = [] |
185 | 924 | branch_revision_map = {} | ||
186 | 925 | for branch_revision_id, sequence, revision_id in rows: | 930 | for branch_revision_id, sequence, revision_id in rows: |
187 | 926 | ancestry.add(revision_id) | 931 | ancestry.add(revision_id) |
188 | 927 | branch_revision_map[revision_id] = branch_revision_id | ||
189 | 928 | if sequence is not None: | 932 | if sequence is not None: |
190 | 929 | history.append(revision_id) | 933 | history.append(revision_id) |
192 | 930 | return ancestry, history, branch_revision_map | 934 | return ancestry, history |
193 | 931 | 935 | ||
194 | 932 | def getPullURL(self): | 936 | def getPullURL(self): |
195 | 933 | """See `IBranch`.""" | 937 | """See `IBranch`.""" |
196 | 934 | 938 | ||
197 | === modified file 'lib/lp/code/model/branchrevision.py' | |||
198 | --- lib/lp/code/model/branchrevision.py 2010-08-20 20:31:18 +0000 | |||
199 | +++ lib/lp/code/model/branchrevision.py 2010-09-09 20:24:49 +0000 | |||
200 | @@ -4,7 +4,9 @@ | |||
201 | 4 | # pylint: disable-msg=E0611,W0212 | 4 | # pylint: disable-msg=E0611,W0212 |
202 | 5 | 5 | ||
203 | 6 | __metaclass__ = type | 6 | __metaclass__ = type |
205 | 7 | __all__ = ['BranchRevision', 'BranchRevisionSet'] | 7 | __all__ = [ |
206 | 8 | 'BranchRevision', | ||
207 | 9 | ] | ||
208 | 8 | 10 | ||
209 | 9 | from storm.locals import ( | 11 | from storm.locals import ( |
210 | 10 | Int, | 12 | Int, |
211 | @@ -13,11 +15,7 @@ | |||
212 | 13 | ) | 15 | ) |
213 | 14 | from zope.interface import implements | 16 | from zope.interface import implements |
214 | 15 | 17 | ||
220 | 16 | from canonical.launchpad.interfaces.lpstorm import IMasterStore | 18 | from lp.code.interfaces.branchrevision import IBranchRevision |
216 | 17 | from lp.code.interfaces.branchrevision import ( | ||
217 | 18 | IBranchRevision, | ||
218 | 19 | IBranchRevisionSet, | ||
219 | 20 | ) | ||
221 | 21 | 19 | ||
222 | 22 | 20 | ||
223 | 23 | class BranchRevision(Storm): | 21 | class BranchRevision(Storm): |
224 | @@ -40,15 +38,3 @@ | |||
225 | 40 | self.branch = branch | 38 | self.branch = branch |
226 | 41 | self.revision = revision | 39 | self.revision = revision |
227 | 42 | self.sequence = sequence | 40 | self.sequence = sequence |
228 | 43 | |||
229 | 44 | |||
230 | 45 | class BranchRevisionSet: | ||
231 | 46 | """See `IBranchRevisionSet`.""" | ||
232 | 47 | |||
233 | 48 | implements(IBranchRevisionSet) | ||
234 | 49 | |||
235 | 50 | def delete(self, branch_revision_id): | ||
236 | 51 | """See `IBranchRevisionSet`.""" | ||
237 | 52 | match = IMasterStore(BranchRevision).find( | ||
238 | 53 | BranchRevision, BranchRevision.id == branch_revision_id) | ||
239 | 54 | match.remove() | ||
240 | 55 | 41 | ||
241 | === modified file 'lib/lp/code/model/tests/test_branch.py' | |||
242 | --- lib/lp/code/model/tests/test_branch.py 2010-09-03 00:25:53 +0000 | |||
243 | +++ lib/lp/code/model/tests/test_branch.py 2010-09-09 20:24:49 +0000 | |||
244 | @@ -29,6 +29,7 @@ | |||
245 | 29 | from canonical.database.constants import UTC_NOW | 29 | from canonical.database.constants import UTC_NOW |
246 | 30 | from canonical.launchpad import _ | 30 | from canonical.launchpad import _ |
247 | 31 | from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities | 31 | from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities |
248 | 32 | from canonical.launchpad.interfaces.lpstorm import IStore | ||
249 | 32 | from canonical.launchpad.webapp.interfaces import IOpenLaunchBag | 33 | from canonical.launchpad.webapp.interfaces import IOpenLaunchBag |
250 | 33 | from canonical.testing import ( | 34 | from canonical.testing import ( |
251 | 34 | DatabaseFunctionalLayer, | 35 | DatabaseFunctionalLayer, |
252 | @@ -100,16 +101,16 @@ | |||
253 | 100 | ReclaimBranchSpaceJob, | 101 | ReclaimBranchSpaceJob, |
254 | 101 | ) | 102 | ) |
255 | 102 | from lp.code.model.branchmergeproposal import BranchMergeProposal | 103 | from lp.code.model.branchmergeproposal import BranchMergeProposal |
256 | 104 | from lp.code.model.branchrevision import BranchRevision | ||
257 | 103 | from lp.code.model.codeimport import ( | 105 | from lp.code.model.codeimport import ( |
258 | 104 | CodeImport, | 106 | CodeImport, |
259 | 105 | CodeImportSet, | 107 | CodeImportSet, |
260 | 106 | ) | 108 | ) |
261 | 107 | from lp.code.model.codereviewcomment import CodeReviewComment | 109 | from lp.code.model.codereviewcomment import CodeReviewComment |
262 | 110 | from lp.code.model.revision import Revision | ||
263 | 108 | from lp.code.tests.helpers import add_revision_to_branch | 111 | from lp.code.tests.helpers import add_revision_to_branch |
264 | 109 | from lp.codehosting.bzrutils import UnsafeUrlSeen | 112 | from lp.codehosting.bzrutils import UnsafeUrlSeen |
265 | 110 | from lp.registry.interfaces.person import IPersonSet | ||
266 | 111 | from lp.registry.interfaces.pocket import PackagePublishingPocket | 113 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
267 | 112 | from lp.registry.model.product import ProductSet | ||
268 | 113 | from lp.registry.model.sourcepackage import SourcePackage | 114 | from lp.registry.model.sourcepackage import SourcePackage |
269 | 114 | from lp.services.osutils import override_environ | 115 | from lp.services.osutils import override_environ |
270 | 115 | from lp.testing import ( | 116 | from lp.testing import ( |
271 | @@ -252,6 +253,59 @@ | |||
272 | 252 | branch.repository_format)) | 253 | branch.repository_format)) |
273 | 253 | 254 | ||
274 | 254 | 255 | ||
275 | 256 | class TestBranchRevisionMethods(TestCaseWithFactory): | ||
276 | 257 | """Test the branch methods for adding and removing branch revisions.""" | ||
277 | 258 | |||
278 | 259 | layer = DatabaseFunctionalLayer | ||
279 | 260 | |||
280 | 261 | def _getBranchRevision(self, branch, rev_id): | ||
281 | 262 | """Get the branch revision for the specified branch and rev_id.""" | ||
282 | 263 | resultset = IStore(BranchRevision).find( | ||
283 | 264 | BranchRevision, | ||
284 | 265 | BranchRevision.branch == branch, | ||
285 | 266 | BranchRevision.revision == Revision.id, | ||
286 | 267 | Revision.revision_id == rev_id) | ||
287 | 268 | return resultset.one() | ||
288 | 269 | |||
289 | 270 | def test_createBranchRevision(self): | ||
290 | 271 | # createBranchRevision adds the link for the revision to the branch. | ||
291 | 272 | branch = self.factory.makeBranch() | ||
292 | 273 | rev = self.factory.makeRevision() | ||
293 | 274 | # Nothing there to start with. | ||
294 | 275 | self.assertIs(None, self._getBranchRevision(branch, rev.revision_id)) | ||
295 | 276 | branch.createBranchRevision(1, rev) | ||
296 | 277 | # Now there is one. | ||
297 | 278 | br = self._getBranchRevision(branch, rev.revision_id) | ||
298 | 279 | self.assertEqual(branch, br.branch) | ||
299 | 280 | self.assertEqual(rev, br.revision) | ||
300 | 281 | |||
301 | 282 | def test_removeBranchRevisions(self): | ||
302 | 283 | # removeBranchRevisions can remove a single linked revision. | ||
303 | 284 | branch = self.factory.makeBranch() | ||
304 | 285 | rev = self.factory.makeRevision() | ||
305 | 286 | branch.createBranchRevision(1, rev) | ||
306 | 287 | # Now remove the branch revision. | ||
307 | 288 | branch.removeBranchRevisions(rev.revision_id) | ||
308 | 289 | # Revision not there now. | ||
309 | 290 | self.assertIs(None, self._getBranchRevision(branch, rev.revision_id)) | ||
310 | 291 | |||
311 | 292 | def test_removeBranchRevisions_multiple(self): | ||
312 | 293 | # removeBranchRevisions can remove multiple revision links at once. | ||
313 | 294 | branch = self.factory.makeBranch() | ||
314 | 295 | rev1 = self.factory.makeRevision() | ||
315 | 296 | rev2 = self.factory.makeRevision() | ||
316 | 297 | rev3 = self.factory.makeRevision() | ||
317 | 298 | branch.createBranchRevision(1, rev1) | ||
318 | 299 | branch.createBranchRevision(2, rev2) | ||
319 | 300 | branch.createBranchRevision(3, rev3) | ||
320 | 301 | # Now remove the branch revision. | ||
321 | 302 | branch.removeBranchRevisions( | ||
322 | 303 | [rev1.revision_id, rev2.revision_id, rev3.revision_id]) | ||
323 | 304 | # No mainline revisions there now. | ||
324 | 305 | # The revision_history attribute is tested above. | ||
325 | 306 | self.assertEqual([], list(branch.revision_history)) | ||
326 | 307 | |||
327 | 308 | |||
328 | 255 | class TestBranchGetRevision(TestCaseWithFactory): | 309 | class TestBranchGetRevision(TestCaseWithFactory): |
329 | 256 | """Make sure that `Branch.getBranchRevision` works as expected.""" | 310 | """Make sure that `Branch.getBranchRevision` works as expected.""" |
330 | 257 | 311 | ||
331 | 258 | 312 | ||
332 | === modified file 'lib/lp/codehosting/scanner/bzrsync.py' | |||
333 | --- lib/lp/codehosting/scanner/bzrsync.py 2010-08-20 20:31:18 +0000 | |||
334 | +++ lib/lp/codehosting/scanner/bzrsync.py 2010-09-09 20:24:49 +0000 | |||
335 | @@ -21,8 +21,9 @@ | |||
336 | 21 | from zope.component import getUtility | 21 | from zope.component import getUtility |
337 | 22 | from zope.event import notify | 22 | from zope.event import notify |
338 | 23 | 23 | ||
339 | 24 | from canonical.config import config | ||
340 | 25 | |||
341 | 24 | from lp.code.interfaces.branchjob import IRosettaUploadJobSource | 26 | from lp.code.interfaces.branchjob import IRosettaUploadJobSource |
342 | 25 | from lp.code.interfaces.branchrevision import IBranchRevisionSet | ||
343 | 26 | from lp.code.interfaces.revision import IRevisionSet | 27 | from lp.code.interfaces.revision import IRevisionSet |
344 | 27 | from lp.codehosting import iter_list_chunks | 28 | from lp.codehosting import iter_list_chunks |
345 | 28 | from lp.codehosting.scanner import events | 29 | from lp.codehosting.scanner import events |
346 | @@ -82,13 +83,11 @@ | |||
347 | 82 | # written to by the branch-scanner, so they are not subject to | 83 | # written to by the branch-scanner, so they are not subject to |
348 | 83 | # write-lock contention. Update them all in a single transaction to | 84 | # write-lock contention. Update them all in a single transaction to |
349 | 84 | # improve the performance and allow garbage collection in the future. | 85 | # improve the performance and allow garbage collection in the future. |
352 | 85 | db_ancestry, db_history, db_branch_revision_map = ( | 86 | db_ancestry, db_history = self.retrieveDatabaseAncestry() |
351 | 86 | self.retrieveDatabaseAncestry()) | ||
353 | 87 | 87 | ||
354 | 88 | (added_ancestry, branchrevisions_to_delete, | 88 | (added_ancestry, branchrevisions_to_delete, |
355 | 89 | revids_to_insert) = self.planDatabaseChanges( | 89 | revids_to_insert) = self.planDatabaseChanges( |
358 | 90 | bzr_branch, bzr_ancestry, bzr_history, db_ancestry, db_history, | 90 | bzr_branch, bzr_ancestry, bzr_history, db_ancestry, db_history) |
357 | 91 | db_branch_revision_map) | ||
359 | 92 | added_ancestry.difference_update( | 91 | added_ancestry.difference_update( |
360 | 93 | getUtility(IRevisionSet).onlyPresent(added_ancestry)) | 92 | getUtility(IRevisionSet).onlyPresent(added_ancestry)) |
361 | 94 | self.logger.info("Adding %s new revisions.", len(added_ancestry)) | 93 | self.logger.info("Adding %s new revisions.", len(added_ancestry)) |
362 | @@ -129,9 +128,8 @@ | |||
363 | 129 | def retrieveDatabaseAncestry(self): | 128 | def retrieveDatabaseAncestry(self): |
364 | 130 | """Efficiently retrieve ancestry from the database.""" | 129 | """Efficiently retrieve ancestry from the database.""" |
365 | 131 | self.logger.info("Retrieving ancestry from database.") | 130 | self.logger.info("Retrieving ancestry from database.") |
369 | 132 | db_ancestry, db_history, db_branch_revision_map = ( | 131 | db_ancestry, db_history = self.db_branch.getScannerData() |
370 | 133 | self.db_branch.getScannerData()) | 132 | return db_ancestry, db_history |
368 | 134 | return db_ancestry, db_history, db_branch_revision_map | ||
371 | 135 | 133 | ||
372 | 136 | def retrieveBranchDetails(self, bzr_branch): | 134 | def retrieveBranchDetails(self, bzr_branch): |
373 | 137 | """Retrieve ancestry from the the bzr branch on disk.""" | 135 | """Retrieve ancestry from the the bzr branch on disk.""" |
374 | @@ -147,7 +145,7 @@ | |||
375 | 147 | return bzr_ancestry, bzr_history | 145 | return bzr_ancestry, bzr_history |
376 | 148 | 146 | ||
377 | 149 | def planDatabaseChanges(self, bzr_branch, bzr_ancestry, bzr_history, | 147 | def planDatabaseChanges(self, bzr_branch, bzr_ancestry, bzr_history, |
379 | 150 | db_ancestry, db_history, db_branch_revision_map): | 148 | db_ancestry, db_history): |
380 | 151 | """Plan database changes to synchronize with bzrlib data. | 149 | """Plan database changes to synchronize with bzrlib data. |
381 | 152 | 150 | ||
382 | 153 | Use the data retrieved by `retrieveDatabaseAncestry` and | 151 | Use the data retrieved by `retrieveDatabaseAncestry` and |
383 | @@ -190,9 +188,8 @@ | |||
384 | 190 | 188 | ||
385 | 191 | # We must delete BranchRevision rows for all revisions which where | 189 | # We must delete BranchRevision rows for all revisions which where |
386 | 192 | # removed from the ancestry or whose sequence value has changed. | 190 | # removed from the ancestry or whose sequence value has changed. |
390 | 193 | branchrevisions_to_delete = set( | 191 | branchrevisions_to_delete = list( |
391 | 194 | db_branch_revision_map[revid] | 192 | removed_merged.union(removed_history)) |
389 | 195 | for revid in removed_merged.union(removed_history)) | ||
392 | 196 | 193 | ||
393 | 197 | # We must insert BranchRevision rows for all revisions which were | 194 | # We must insert BranchRevision rows for all revisions which were |
394 | 198 | # added to the ancestry or whose sequence value has changed. | 195 | # added to the ancestry or whose sequence value has changed. |
395 | @@ -244,13 +241,19 @@ | |||
396 | 244 | for revision_id in revision_subset.difference(set(bzr_history)): | 241 | for revision_id in revision_subset.difference(set(bzr_history)): |
397 | 245 | yield revision_id, None | 242 | yield revision_id, None |
398 | 246 | 243 | ||
400 | 247 | def deleteBranchRevisions(self, branchrevisions_to_delete): | 244 | def deleteBranchRevisions(self, revision_ids_to_delete): |
401 | 248 | """Delete a batch of BranchRevision rows.""" | 245 | """Delete a batch of BranchRevision rows.""" |
402 | 249 | self.logger.info("Deleting %d branchrevision records.", | 246 | self.logger.info("Deleting %d branchrevision records.", |
407 | 250 | len(branchrevisions_to_delete)) | 247 | len(revision_ids_to_delete)) |
408 | 251 | branch_revision_set = getUtility(IBranchRevisionSet) | 248 | # Use a config value to work out how many to delete at a time. |
409 | 252 | for branchrevision in sorted(branchrevisions_to_delete): | 249 | # Deleting more than one at a time is significantly more efficient |
410 | 253 | branch_revision_set.delete(branchrevision) | 250 | # than doing one at a time, but the actual optimal count is a bit up |
411 | 251 | # in the air. | ||
412 | 252 | batch_size = config.branchscanner.branch_revision_delete_count | ||
413 | 253 | while revision_ids_to_delete: | ||
414 | 254 | batch = revision_ids_to_delete[:batch_size] | ||
415 | 255 | revision_ids_to_delete[:batch_size] = [] | ||
416 | 256 | self.db_branch.removeBranchRevisions(batch) | ||
417 | 254 | 257 | ||
418 | 255 | def insertBranchRevisions(self, bzr_branch, revids_to_insert): | 258 | def insertBranchRevisions(self, bzr_branch, revids_to_insert): |
419 | 256 | """Insert a batch of BranchRevision rows.""" | 259 | """Insert a batch of BranchRevision rows.""" |
420 | 257 | 260 | ||
421 | === modified file 'lib/lp/codehosting/scanner/tests/test_bzrsync.py' | |||
422 | --- lib/lp/codehosting/scanner/tests/test_bzrsync.py 2010-08-20 20:31:18 +0000 | |||
423 | +++ lib/lp/codehosting/scanner/tests/test_bzrsync.py 2010-09-09 20:24:49 +0000 | |||
424 | @@ -490,18 +490,14 @@ | |||
425 | 490 | expected_history = [branch_revision.revision.revision_id | 490 | expected_history = [branch_revision.revision.revision_id |
426 | 491 | for branch_revision in sampledata | 491 | for branch_revision in sampledata |
427 | 492 | if branch_revision.sequence is not None] | 492 | if branch_revision.sequence is not None] |
428 | 493 | expected_mapping = dict( | ||
429 | 494 | (branch_revision.revision.revision_id, branch_revision.id) | ||
430 | 495 | for branch_revision in sampledata) | ||
431 | 496 | 493 | ||
432 | 497 | self.create_branch_and_tree(db_branch=branch) | 494 | self.create_branch_and_tree(db_branch=branch) |
433 | 498 | 495 | ||
434 | 499 | bzrsync = self.makeBzrSync(branch) | 496 | bzrsync = self.makeBzrSync(branch) |
436 | 500 | db_ancestry, db_history, db_branch_revision_map = ( | 497 | db_ancestry, db_history = ( |
437 | 501 | bzrsync.retrieveDatabaseAncestry()) | 498 | bzrsync.retrieveDatabaseAncestry()) |
438 | 502 | self.assertEqual(expected_ancestry, set(db_ancestry)) | 499 | self.assertEqual(expected_ancestry, set(db_ancestry)) |
439 | 503 | self.assertEqual(expected_history, list(db_history)) | 500 | self.assertEqual(expected_history, list(db_history)) |
440 | 504 | self.assertEqual(expected_mapping, db_branch_revision_map) | ||
441 | 505 | 501 | ||
442 | 506 | 502 | ||
443 | 507 | class TestBzrSyncOneRevision(BzrSyncTestCase): | 503 | class TestBzrSyncOneRevision(BzrSyncTestCase): |
Diff is a little extreme as I thought that db-stable had been merged back into devel already.