Merge lp:~jelmer/bzr/move-write-group into lp:bzr
- move-write-group
- Merge into bzr.dev
Proposed by
Jelmer Vernooij
Status: | Rejected |
---|---|
Rejected by: | Jelmer Vernooij |
Proposed branch: | lp:~jelmer/bzr/move-write-group |
Merge into: | lp:bzr |
Diff against target: |
593 lines (+200/-170) 7 files modified
bzrlib/repofmt/knitrepo.py (+1/-1) bzrlib/repository.py (+3/-157) bzrlib/tests/per_repository/__init__.py (+0/-2) bzrlib/tests/per_repository_vf/__init__.py (+2/-0) bzrlib/tests/per_repository_vf/test_refresh_data.py (+13/-4) bzrlib/tests/per_repository_vf/test_write_group.py (+17/-6) bzrlib/vf_repository.py (+164/-0) |
To merge this branch: | bzr merge lp:~jelmer/bzr/move-write-group |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
bzr-core | Pending | ||
Review via email: mp+60807@code.launchpad.net |
Commit message
Description of the change
Move write group infrastructure to bzrlib.
To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) wrote : | # |
Revision history for this message
Jelmer Vernooij (jelmer) wrote : | # |
Actually, I'm going to wait with this. There is too much code that still relies on start_write_
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'bzrlib/repofmt/knitrepo.py' |
2 | --- bzrlib/repofmt/knitrepo.py 2011-05-08 11:34:17 +0000 |
3 | +++ bzrlib/repofmt/knitrepo.py 2011-05-12 15:41:07 +0000 |
4 | @@ -35,11 +35,11 @@ |
5 | from bzrlib.decorators import needs_read_lock, needs_write_lock |
6 | from bzrlib.repository import ( |
7 | InterRepository, |
8 | - IsInWriteGroupError, |
9 | RepositoryFormat, |
10 | ) |
11 | from bzrlib.vf_repository import ( |
12 | InterSameDataRepository, |
13 | + IsInWriteGroupError, |
14 | MetaDirVersionedFileRepository, |
15 | MetaDirVersionedFileRepositoryFormat, |
16 | VersionedFileCommitBuilder, |
17 | |
18 | === modified file 'bzrlib/repository.py' |
19 | --- bzrlib/repository.py 2011-05-09 12:01:12 +0000 |
20 | +++ bzrlib/repository.py 2011-05-12 15:41:07 +0000 |
21 | @@ -46,21 +46,15 @@ |
22 | from bzrlib.inter import InterObject |
23 | from bzrlib.lock import _RelockDebugMixin, LogicalLockResult |
24 | from bzrlib.trace import ( |
25 | - log_exception_quietly, note, mutter, mutter_callsite, warning) |
26 | + mutter_callsite, |
27 | + warning, |
28 | + ) |
29 | |
30 | |
31 | # Old formats display a warning, but only once |
32 | _deprecation_warning_done = False |
33 | |
34 | |
35 | -class IsInWriteGroupError(errors.InternalBzrError): |
36 | - |
37 | - _fmt = "May not refresh_data of repo %(repo)s while in a write group." |
38 | - |
39 | - def __init__(self, repo): |
40 | - errors.InternalBzrError.__init__(self, repo=repo) |
41 | - |
42 | - |
43 | class CommitBuilder(object): |
44 | """Provides an interface to build up a commit. |
45 | |
46 | @@ -252,49 +246,6 @@ |
47 | base class for most Bazaar repositories. |
48 | """ |
49 | |
50 | - def abort_write_group(self, suppress_errors=False): |
51 | - """Commit the contents accrued within the current write group. |
52 | - |
53 | - :param suppress_errors: if true, abort_write_group will catch and log |
54 | - unexpected errors that happen during the abort, rather than |
55 | - allowing them to propagate. Defaults to False. |
56 | - |
57 | - :seealso: start_write_group. |
58 | - """ |
59 | - if self._write_group is not self.get_transaction(): |
60 | - # has an unlock or relock occured ? |
61 | - if suppress_errors: |
62 | - mutter( |
63 | - '(suppressed) mismatched lock context and write group. %r, %r', |
64 | - self._write_group, self.get_transaction()) |
65 | - return |
66 | - raise errors.BzrError( |
67 | - 'mismatched lock context and write group. %r, %r' % |
68 | - (self._write_group, self.get_transaction())) |
69 | - try: |
70 | - self._abort_write_group() |
71 | - except Exception, exc: |
72 | - self._write_group = None |
73 | - if not suppress_errors: |
74 | - raise |
75 | - mutter('abort_write_group failed') |
76 | - log_exception_quietly() |
77 | - note('bzr: ERROR (ignored): %s', exc) |
78 | - self._write_group = None |
79 | - |
80 | - def _abort_write_group(self): |
81 | - """Template method for per-repository write group cleanup. |
82 | - |
83 | - This is called during abort before the write group is considered to be |
84 | - finished and should cleanup any internal state accrued during the write |
85 | - group. There is no requirement that data handed to the repository be |
86 | - *not* made available - this is not a rollback - but neither should any |
87 | - attempt be made to ensure that data added is fully commited. Abort is |
88 | - invoked when an error has occured so futher disk or network operations |
89 | - may not be possible or may error and if possible should not be |
90 | - attempted. |
91 | - """ |
92 | - |
93 | def add_fallback_repository(self, repository): |
94 | """Add a repository to use for looking up data not held locally. |
95 | |
96 | @@ -373,8 +324,6 @@ |
97 | self.control_files = control_files |
98 | self._transport = control_files._transport |
99 | self.base = self._transport.base |
100 | - # for tests |
101 | - self._write_group = None |
102 | # Additional places to query for data. |
103 | self._fallback_repositories = [] |
104 | |
105 | @@ -418,13 +367,6 @@ |
106 | return False |
107 | return (self._transport.base == other._transport.base) |
108 | |
109 | - def is_in_write_group(self): |
110 | - """Return True if there is an open write group. |
111 | - |
112 | - :seealso: start_write_group. |
113 | - """ |
114 | - return self._write_group is not None |
115 | - |
116 | def is_locked(self): |
117 | return self.control_files.is_locked() |
118 | |
119 | @@ -624,59 +566,6 @@ |
120 | """ |
121 | return InterRepository.get(self, destination).copy_content(revision_id) |
122 | |
123 | - def commit_write_group(self): |
124 | - """Commit the contents accrued within the current write group. |
125 | - |
126 | - :seealso: start_write_group. |
127 | - |
128 | - :return: it may return an opaque hint that can be passed to 'pack'. |
129 | - """ |
130 | - if self._write_group is not self.get_transaction(): |
131 | - # has an unlock or relock occured ? |
132 | - raise errors.BzrError('mismatched lock context %r and ' |
133 | - 'write group %r.' % |
134 | - (self.get_transaction(), self._write_group)) |
135 | - result = self._commit_write_group() |
136 | - self._write_group = None |
137 | - return result |
138 | - |
139 | - def _commit_write_group(self): |
140 | - """Template method for per-repository write group cleanup. |
141 | - |
142 | - This is called before the write group is considered to be |
143 | - finished and should ensure that all data handed to the repository |
144 | - for writing during the write group is safely committed (to the |
145 | - extent possible considering file system caching etc). |
146 | - """ |
147 | - |
148 | - def suspend_write_group(self): |
149 | - raise errors.UnsuspendableWriteGroup(self) |
150 | - |
151 | - def refresh_data(self): |
152 | - """Re-read any data needed to synchronise with disk. |
153 | - |
154 | - This method is intended to be called after another repository instance |
155 | - (such as one used by a smart server) has inserted data into the |
156 | - repository. On all repositories this will work outside of write groups. |
157 | - Some repository formats (pack and newer for bzrlib native formats) |
158 | - support refresh_data inside write groups. If called inside a write |
159 | - group on a repository that does not support refreshing in a write group |
160 | - IsInWriteGroupError will be raised. |
161 | - """ |
162 | - self._refresh_data() |
163 | - |
164 | - def resume_write_group(self, tokens): |
165 | - if not self.is_write_locked(): |
166 | - raise errors.NotWriteLocked(self) |
167 | - if self._write_group: |
168 | - raise errors.BzrError('already in a write group') |
169 | - self._resume_write_group(tokens) |
170 | - # so we can detect unlock/relock - the write group is now entered. |
171 | - self._write_group = self.get_transaction() |
172 | - |
173 | - def _resume_write_group(self, tokens): |
174 | - raise errors.UnsuspendableWriteGroup(self) |
175 | - |
176 | def fetch(self, source, revision_id=None, find_ghosts=False, |
177 | fetch_spec=None): |
178 | """Fetch the content required to construct revision_id from source. |
179 | @@ -684,10 +573,6 @@ |
180 | If revision_id is None and fetch_spec is None, then all content is |
181 | copied. |
182 | |
183 | - fetch() may not be used when the repository is in a write group - |
184 | - either finish the current write group before using fetch, or use |
185 | - fetch before starting the write group. |
186 | - |
187 | :param find_ghosts: Find and copy revisions in the source that are |
188 | ghosts in the target (and not reachable directly by walking out to |
189 | the first-present revision in target from revision_id). |
190 | @@ -702,9 +587,6 @@ |
191 | if fetch_spec is not None and revision_id is not None: |
192 | raise AssertionError( |
193 | "fetch_spec and revision_id are mutually exclusive.") |
194 | - if self.is_in_write_group(): |
195 | - raise errors.InternalBzrError( |
196 | - "May not fetch while in a write group.") |
197 | # fast path same-url fetch operations |
198 | # TODO: lift out to somewhere common with RemoteRepository |
199 | # <https://bugs.launchpad.net/bzr/+bug/401646> |
200 | @@ -744,13 +626,6 @@ |
201 | |
202 | @only_raises(errors.LockNotHeld, errors.LockBroken) |
203 | def unlock(self): |
204 | - if (self.control_files._lock_count == 1 and |
205 | - self.control_files._lock_mode == 'w'): |
206 | - if self._write_group is not None: |
207 | - self.abort_write_group() |
208 | - self.control_files.unlock() |
209 | - raise errors.BzrError( |
210 | - 'Must end write groups before releasing write locks.') |
211 | self.control_files.unlock() |
212 | if self.control_files._lock_count == 0: |
213 | for repo in self._fallback_repositories: |
214 | @@ -771,35 +646,6 @@ |
215 | self.copy_content_into(dest_repo, revision_id) |
216 | return dest_repo |
217 | |
218 | - def start_write_group(self): |
219 | - """Start a write group in the repository. |
220 | - |
221 | - Write groups are used by repositories which do not have a 1:1 mapping |
222 | - between file ids and backend store to manage the insertion of data from |
223 | - both fetch and commit operations. |
224 | - |
225 | - A write lock is required around the start_write_group/commit_write_group |
226 | - for the support of lock-requiring repository formats. |
227 | - |
228 | - One can only insert data into a repository inside a write group. |
229 | - |
230 | - :return: None. |
231 | - """ |
232 | - if not self.is_write_locked(): |
233 | - raise errors.NotWriteLocked(self) |
234 | - if self._write_group: |
235 | - raise errors.BzrError('already in a write group') |
236 | - self._start_write_group() |
237 | - # so we can detect unlock/relock - the write group is now entered. |
238 | - self._write_group = self.get_transaction() |
239 | - |
240 | - def _start_write_group(self): |
241 | - """Template method for per-repository write group startup. |
242 | - |
243 | - This is called before the write group is considered to be |
244 | - entered. |
245 | - """ |
246 | - |
247 | @needs_read_lock |
248 | def sprout(self, to_bzrdir, revision_id=None): |
249 | """Create a descendent repository for new development. |
250 | |
251 | === modified file 'bzrlib/tests/per_repository/__init__.py' |
252 | --- bzrlib/tests/per_repository/__init__.py 2011-05-09 17:52:54 +0000 |
253 | +++ bzrlib/tests/per_repository/__init__.py 2011-05-12 15:41:07 +0000 |
254 | @@ -124,11 +124,9 @@ |
255 | 'test_merge_directive', |
256 | 'test_pack', |
257 | 'test_reconcile', |
258 | - 'test_refresh_data', |
259 | 'test_repository', |
260 | 'test_revision', |
261 | 'test_statistics', |
262 | - 'test_write_group', |
263 | ] |
264 | # Parameterize per_repository test modules by format. |
265 | submod_tests = loader.loadTestsFromModuleNames( |
266 | |
267 | === modified file 'bzrlib/tests/per_repository_vf/__init__.py' |
268 | --- bzrlib/tests/per_repository_vf/__init__.py 2011-05-09 17:52:54 +0000 |
269 | +++ bzrlib/tests/per_repository_vf/__init__.py 2011-05-12 15:41:07 +0000 |
270 | @@ -43,7 +43,9 @@ |
271 | 'test__generate_text_key_index', |
272 | 'test_fetch', |
273 | 'test_reconcile', |
274 | + 'test_refresh_data', |
275 | 'test_repository', |
276 | + 'test_write_group', |
277 | ] |
278 | basic_tests.addTest(loader.loadTestsFromModuleNames( |
279 | ["%s.%s" % (__name__, tmn) for tmn in testmod_names])) |
280 | |
281 | === renamed file 'bzrlib/tests/per_repository/test_refresh_data.py' => 'bzrlib/tests/per_repository_vf/test_refresh_data.py' |
282 | --- bzrlib/tests/per_repository/test_refresh_data.py 2010-05-11 14:14:55 +0000 |
283 | +++ bzrlib/tests/per_repository_vf/test_refresh_data.py 2011-05-12 15:41:07 +0000 |
284 | @@ -18,14 +18,23 @@ |
285 | |
286 | from bzrlib import ( |
287 | errors, |
288 | - repository, |
289 | + vf_repository, |
290 | ) |
291 | +from bzrlib.tests.scenarios import load_tests_apply_scenarios |
292 | from bzrlib.tests import TestSkipped |
293 | -from bzrlib.tests.per_repository import TestCaseWithRepository |
294 | +from bzrlib.tests.per_repository_vf import ( |
295 | + TestCaseWithRepository, |
296 | + all_repository_vf_format_scenarios, |
297 | + ) |
298 | + |
299 | + |
300 | +load_tests = load_tests_apply_scenarios |
301 | |
302 | |
303 | class TestRefreshData(TestCaseWithRepository): |
304 | |
305 | + scenarios = all_repository_vf_format_scenarios() |
306 | + |
307 | def test_refresh_data_unlocked(self): |
308 | # While not interesting, it should not error. |
309 | repo = self.make_repository('.') |
310 | @@ -55,7 +64,7 @@ |
311 | self.addCleanup(repo.abort_write_group) |
312 | try: |
313 | repo.refresh_data() |
314 | - except repository.IsInWriteGroupError: |
315 | + except vf_repository.IsInWriteGroupError: |
316 | # This is ok. |
317 | pass |
318 | else: |
319 | @@ -112,7 +121,7 @@ |
320 | # succeeds and the new revisions are visible. |
321 | try: |
322 | repo.refresh_data() |
323 | - except repository.IsInWriteGroupError: |
324 | + except vf_repository.IsInWriteGroupError: |
325 | pass |
326 | else: |
327 | self.assertEqual( |
328 | |
329 | === renamed file 'bzrlib/tests/per_repository/test_write_group.py' => 'bzrlib/tests/per_repository_vf/test_write_group.py' |
330 | --- bzrlib/tests/per_repository/test_write_group.py 2011-01-10 23:52:14 +0000 |
331 | +++ bzrlib/tests/per_repository_vf/test_write_group.py 2011-05-12 15:41:07 +0000 |
332 | @@ -22,21 +22,28 @@ |
333 | branch, |
334 | bzrdir, |
335 | errors, |
336 | - graph, |
337 | memorytree, |
338 | - osutils, |
339 | remote, |
340 | tests, |
341 | versionedfile, |
342 | ) |
343 | from bzrlib.tests import ( |
344 | - per_repository, |
345 | test_server, |
346 | ) |
347 | +from bzrlib.tests.per_repository_vf import ( |
348 | + TestCaseWithRepository, |
349 | + all_repository_vf_format_scenarios, |
350 | + ) |
351 | +from bzrlib.tests.scenarios import load_tests_apply_scenarios |
352 | from bzrlib.transport import memory |
353 | |
354 | |
355 | -class TestWriteGroup(per_repository.TestCaseWithRepository): |
356 | +load_tests = load_tests_apply_scenarios |
357 | + |
358 | + |
359 | +class TestWriteGroup(TestCaseWithRepository): |
360 | + |
361 | + scenarios = all_repository_vf_format_scenarios() |
362 | |
363 | def test_start_write_group_unlocked_needs_write_lock(self): |
364 | repo = self.make_repository('.') |
365 | @@ -134,7 +141,9 @@ |
366 | self.assertEqual(None, repo.abort_write_group(suppress_errors=True)) |
367 | |
368 | |
369 | -class TestGetMissingParentInventories(per_repository.TestCaseWithRepository): |
370 | +class TestGetMissingParentInventories(TestCaseWithRepository): |
371 | + |
372 | + scenarios = all_repository_vf_format_scenarios() |
373 | |
374 | def test_empty_get_missing_parent_inventories(self): |
375 | """A new write group has no missing parent inventories.""" |
376 | @@ -393,7 +402,9 @@ |
377 | |
378 | |
379 | |
380 | -class TestResumeableWriteGroup(per_repository.TestCaseWithRepository): |
381 | +class TestResumeableWriteGroup(TestCaseWithRepository): |
382 | + |
383 | + scenarios = all_repository_vf_format_scenarios() |
384 | |
385 | def make_write_locked_repo(self, relpath='repo'): |
386 | repo = self.make_repository(relpath) |
387 | |
388 | === modified file 'bzrlib/vf_repository.py' |
389 | --- bzrlib/vf_repository.py 2011-05-08 13:06:20 +0000 |
390 | +++ bzrlib/vf_repository.py 2011-05-12 15:41:07 +0000 |
391 | @@ -66,10 +66,20 @@ |
392 | ) |
393 | |
394 | from bzrlib.trace import ( |
395 | + log_exception_quietly, |
396 | mutter, |
397 | + note, |
398 | ) |
399 | |
400 | |
401 | +class IsInWriteGroupError(errors.InternalBzrError): |
402 | + |
403 | + _fmt = "May not refresh_data of repo %(repo)s while in a write group." |
404 | + |
405 | + def __init__(self, repo): |
406 | + errors.InternalBzrError.__init__(self, repo=repo) |
407 | + |
408 | + |
409 | class VersionedFileRepositoryFormat(RepositoryFormat): |
410 | """Base class for all repository formats that are VersionedFiles-based.""" |
411 | |
412 | @@ -899,6 +909,138 @@ |
413 | # get_commit_builder. |
414 | _commit_builder_class = VersionedFileCommitBuilder |
415 | |
416 | + def start_write_group(self): |
417 | + """Start a write group in the repository. |
418 | + |
419 | + Write groups are used by repositories which do not have a 1:1 mapping |
420 | + between file ids and backend store to manage the insertion of data from |
421 | + both fetch and commit operations. |
422 | + |
423 | + A write lock is required around the start_write_group/commit_write_group |
424 | + for the support of lock-requiring repository formats. |
425 | + |
426 | + One can only insert data into a repository inside a write group. |
427 | + |
428 | + :return: None. |
429 | + """ |
430 | + if not self.is_write_locked(): |
431 | + raise errors.NotWriteLocked(self) |
432 | + if self._write_group: |
433 | + raise errors.BzrError('already in a write group') |
434 | + self._start_write_group() |
435 | + # so we can detect unlock/relock - the write group is now entered. |
436 | + self._write_group = self.get_transaction() |
437 | + |
438 | + def _start_write_group(self): |
439 | + """Template method for per-repository write group startup. |
440 | + |
441 | + This is called before the write group is considered to be |
442 | + entered. |
443 | + """ |
444 | + |
445 | + def abort_write_group(self, suppress_errors=False): |
446 | + """Commit the contents accrued within the current write group. |
447 | + |
448 | + :param suppress_errors: if true, abort_write_group will catch and log |
449 | + unexpected errors that happen during the abort, rather than |
450 | + allowing them to propagate. Defaults to False. |
451 | + |
452 | + :seealso: start_write_group. |
453 | + """ |
454 | + if self._write_group is not self.get_transaction(): |
455 | + # has an unlock or relock occured ? |
456 | + if suppress_errors: |
457 | + mutter( |
458 | + '(suppressed) mismatched lock context and write group. %r, %r', |
459 | + self._write_group, self.get_transaction()) |
460 | + return |
461 | + raise errors.BzrError( |
462 | + 'mismatched lock context and write group. %r, %r' % |
463 | + (self._write_group, self.get_transaction())) |
464 | + try: |
465 | + self._abort_write_group() |
466 | + except Exception, exc: |
467 | + self._write_group = None |
468 | + if not suppress_errors: |
469 | + raise |
470 | + mutter('abort_write_group failed') |
471 | + log_exception_quietly() |
472 | + note('bzr: ERROR (ignored): %s', exc) |
473 | + self._write_group = None |
474 | + |
475 | + def _abort_write_group(self): |
476 | + """Template method for per-repository write group cleanup. |
477 | + |
478 | + This is called during abort before the write group is considered to be |
479 | + finished and should cleanup any internal state accrued during the write |
480 | + group. There is no requirement that data handed to the repository be |
481 | + *not* made available - this is not a rollback - but neither should any |
482 | + attempt be made to ensure that data added is fully commited. Abort is |
483 | + invoked when an error has occured so futher disk or network operations |
484 | + may not be possible or may error and if possible should not be |
485 | + attempted. |
486 | + """ |
487 | + |
488 | + def is_in_write_group(self): |
489 | + """Return True if there is an open write group. |
490 | + |
491 | + :seealso: start_write_group. |
492 | + """ |
493 | + return self._write_group is not None |
494 | + |
495 | + def commit_write_group(self): |
496 | + """Commit the contents accrued within the current write group. |
497 | + |
498 | + :seealso: start_write_group. |
499 | + |
500 | + :return: it may return an opaque hint that can be passed to 'pack'. |
501 | + """ |
502 | + if self._write_group is not self.get_transaction(): |
503 | + # has an unlock or relock occured ? |
504 | + raise errors.BzrError('mismatched lock context %r and ' |
505 | + 'write group %r.' % |
506 | + (self.get_transaction(), self._write_group)) |
507 | + result = self._commit_write_group() |
508 | + self._write_group = None |
509 | + return result |
510 | + |
511 | + def _commit_write_group(self): |
512 | + """Template method for per-repository write group cleanup. |
513 | + |
514 | + This is called before the write group is considered to be |
515 | + finished and should ensure that all data handed to the repository |
516 | + for writing during the write group is safely committed (to the |
517 | + extent possible considering file system caching etc). |
518 | + """ |
519 | + |
520 | + def suspend_write_group(self): |
521 | + raise errors.UnsuspendableWriteGroup(self) |
522 | + |
523 | + def resume_write_group(self, tokens): |
524 | + if not self.is_write_locked(): |
525 | + raise errors.NotWriteLocked(self) |
526 | + if self._write_group: |
527 | + raise errors.BzrError('already in a write group') |
528 | + self._resume_write_group(tokens) |
529 | + # so we can detect unlock/relock - the write group is now entered. |
530 | + self._write_group = self.get_transaction() |
531 | + |
532 | + def _resume_write_group(self, tokens): |
533 | + raise errors.UnsuspendableWriteGroup(self) |
534 | + |
535 | + def refresh_data(self): |
536 | + """Re-read any data needed to synchronise with disk. |
537 | + |
538 | + This method is intended to be called after another repository instance |
539 | + (such as one used by a smart server) has inserted data into the |
540 | + repository. On all repositories this will work outside of write groups. |
541 | + Some repository formats (pack and newer for bzrlib native formats) |
542 | + support refresh_data inside write groups. If called inside a write |
543 | + group on a repository that does not support refreshing in a write group |
544 | + IsInWriteGroupError will be raised. |
545 | + """ |
546 | + self._refresh_data() |
547 | + |
548 | def add_fallback_repository(self, repository): |
549 | """Add a repository to use for looking up data not held locally. |
550 | |
551 | @@ -921,6 +1063,13 @@ |
552 | |
553 | @only_raises(errors.LockNotHeld, errors.LockBroken) |
554 | def unlock(self): |
555 | + if (self.control_files._lock_count == 1 and |
556 | + self.control_files._lock_mode == 'w'): |
557 | + if self._write_group is not None: |
558 | + self.abort_write_group() |
559 | + self.control_files.unlock() |
560 | + raise errors.BzrError( |
561 | + 'Must end write groups before releasing write locks.') |
562 | super(VersionedFileRepository, self).unlock() |
563 | if self.control_files._lock_count == 0: |
564 | self._inventory_entry_cache.clear() |
565 | @@ -1189,6 +1338,7 @@ |
566 | # Is it safe to return inventory entries directly from the entry cache, |
567 | # rather copying them? |
568 | self._safe_to_return_from_cache = False |
569 | + self._write_group = None |
570 | |
571 | @needs_read_lock |
572 | def gather_stats(self, revid=None, committers=None): |
573 | @@ -1204,6 +1354,20 @@ |
574 | # result['size'] = t |
575 | return result |
576 | |
577 | + def fetch(self, source, revision_id=None, find_ghosts=False, |
578 | + fetch_spec=None): |
579 | + """See Repository.fetch(). |
580 | + |
581 | + fetch() may not be used when the repository is in a write group - |
582 | + either finish the current write group before using fetch, or use |
583 | + fetch before starting the write group. |
584 | + """ |
585 | + if self.is_in_write_group(): |
586 | + raise errors.InternalBzrError( |
587 | + "May not fetch while in a write group.") |
588 | + return super(VersionedFileRepository, self).fetch(source, |
589 | + revision_id=revision_id, find_ghosts=find_ghosts, |
590 | + fetch_spec=fetch_spec) |
591 | |
592 | def get_commit_builder(self, branch, parents, config, timestamp=None, |
593 | timezone=None, committer=None, revprops=None, |
The only semi-generic thing that still requires the use of write groups is Repository. sign_revision( ). I've filed bug 781751 about this.