7
7
# it under the terms of the GNU General Public License as published by
8
8
# the Free Software Foundation; either version 2 of the License, or
9
9
# (at your option) any later version.
11
11
# This program is distributed in the hope that it will be useful,
12
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
14
# GNU General Public License for more details.
16
16
# You should have received a copy of the GNU General Public License
17
17
# along with this program; if not, write to the Free Software
18
18
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
20
"""Versioned text file storage api."""
22
from bzrlib.lazy_import import lazy_import
23
lazy_import(globals(), """
23
24
from copy import deepcopy
24
from unittest import TestSuite
27
import bzrlib.errors as errors
34
from bzrlib.transport.memory import MemoryTransport
28
37
from bzrlib.inter import InterObject
29
from bzrlib.symbol_versioning import *
30
38
from bzrlib.textmerge import TextMerge
31
from bzrlib.transport.memory import MemoryTransport
32
from bzrlib.tsort import topo_sort
39
from bzrlib.symbol_versioning import (deprecated_function,
36
45
class VersionedFile(object):
51
60
self.finished = False
52
61
self._access_mode = access_mode
64
def check_not_reserved_id(version_id):
65
revision.check_not_reserved_id(version_id)
54
67
def copy_to(self, name, transport):
55
68
"""Copy this versioned file to name on transport."""
56
69
raise NotImplementedError(self.copy_to)
58
71
@deprecated_method(zero_eight)
60
73
"""Return a list of all the versions in this versioned file.
84
97
:param sha1: The sha1 of the full text.
85
98
:param delta: The delta instructions. See get_delta for details.
100
version_id = osutils.safe_revision_id(version_id)
101
parents = [osutils.safe_revision_id(v) for v in parents]
87
102
self._check_write_ok()
88
103
if self.has_version(version_id):
89
104
raise errors.RevisionAlreadyPresent(version_id, self)
126
141
provided back to future add_lines calls in the parent_texts
144
version_id = osutils.safe_revision_id(version_id)
145
parents = [osutils.safe_revision_id(v) for v in parents]
129
146
self._check_write_ok()
130
147
return self._add_lines(version_id, parents, lines, parent_texts)
140
157
This takes the same parameters as add_lines.
159
version_id = osutils.safe_revision_id(version_id)
160
parents = [osutils.safe_revision_id(v) for v in parents]
142
161
self._check_write_ok()
143
162
return self._add_lines_with_ghosts(version_id, parents, lines,
170
189
if self._access_mode != 'w':
171
190
raise errors.ReadOnlyObjectDirtiedError(self)
192
def enable_cache(self):
193
"""Tell this versioned file that it should cache any data it reads.
195
This is advisory, implementations do not have to support caching.
173
199
def clear_cache(self):
174
"""Remove any data cached in the versioned file object."""
200
"""Remove any data cached in the versioned file object.
202
This only needs to be supported if caches are supported
176
206
def clone_text(self, new_version_id, old_version_id, parents):
177
207
"""Add an identical text to old_version_id as new_version_id.
182
212
Must raise RevisionAlreadyPresent if the new version is
183
213
already present in file history."""
214
new_version_id = osutils.safe_revision_id(new_version_id)
215
old_version_id = osutils.safe_revision_id(old_version_id)
184
216
self._check_write_ok()
185
217
return self._clone_text(new_version_id, old_version_id, parents)
198
230
raise NotImplementedError(self.create_empty)
200
def fix_parents(self, version, new_parents):
232
def fix_parents(self, version_id, new_parents):
201
233
"""Fix the parents list for version.
203
235
This is done by appending a new version to the index
205
237
the parents list must be a superset of the current
240
version_id = osutils.safe_revision_id(version_id)
241
new_parents = [osutils.safe_revision_id(p) for p in new_parents]
208
242
self._check_write_ok()
209
return self._fix_parents(version, new_parents)
243
return self._fix_parents(version_id, new_parents)
211
def _fix_parents(self, version, new_parents):
245
def _fix_parents(self, version_id, new_parents):
212
246
"""Helper for fix_parents."""
213
247
raise NotImplementedError(self.fix_parents)
221
255
raise NotImplementedError(self.get_delta)
223
def get_deltas(self, versions):
257
def get_deltas(self, version_ids):
224
258
"""Get multiple deltas at once for constructing versions.
226
260
:return: dict(version_id:(delta_parent, sha1, noeol, delta))
228
262
version_id is the version_id created by that delta.
231
for version in versions:
232
result[version] = self.get_delta(version)
265
for version_id in version_ids:
266
result[version_id] = self.get_delta(version_id)
235
269
def get_sha1(self, version_id):
252
286
return ''.join(self.get_lines(version_id))
253
287
get_string = get_text
289
def get_texts(self, version_ids):
290
"""Return the texts of listed versions as a list of strings.
292
Raises RevisionNotPresent if version is not present in
295
return [''.join(self.get_lines(v)) for v in version_ids]
255
297
def get_lines(self, version_id):
256
298
"""Return version contents as a sequence of lines.
288
330
Ghosts are not listed or referenced in the graph.
289
331
:param version_ids: Versions to select.
290
None means retreive all versions.
332
None means retrieve all versions.
293
335
if version_ids is None:
294
336
for version in self.versions():
295
337
result[version] = self.get_parents(version)
297
pending = set(version_ids)
339
pending = set(osutils.safe_revision_id(v) for v in version_ids)
299
341
version = pending.pop()
300
342
if version in result:
384
def iter_lines_added_or_present_in_versions(self, version_ids=None):
426
def iter_lines_added_or_present_in_versions(self, version_ids=None,
385
428
"""Iterate over the lines in the versioned file from version_ids.
387
430
This may return lines from other versions, and does not return the
388
431
specific version marker at this point. The api may be changed
389
432
during development to include the version that the versioned file
390
433
thinks is relevant, but given that such hints are just guesses,
391
its better not to have it if we dont need it.
434
its better not to have it if we don't need it.
436
If a progress bar is supplied, it may be used to indicate progress.
437
The caller is responsible for cleaning up progress bars (because this
393
440
NOTES: Lines are normalised: they will all have \n terminators.
394
441
Lines are returned in arbitrary order.
447
494
raise NotImplementedError(VersionedFile.plan_merge)
449
def weave_merge(self, plan, a_marker=TextMerge.A_MARKER,
496
def weave_merge(self, plan, a_marker=TextMerge.A_MARKER,
450
497
b_marker=TextMerge.B_MARKER):
451
498
return PlanWeaveMerge(plan, a_marker, b_marker).merge_lines()[0]
484
531
# We previously considered either 'unchanged' or 'killed-both' lines
485
532
# to be possible places to resynchronize. However, assuming agreement
486
# on killed-both lines may be too agressive. -- mbp 20060324
533
# on killed-both lines may be too aggressive. -- mbp 20060324
487
534
for state, line in self.plan:
488
535
if state == 'unchanged':
489
536
# resync and flush queued conflicts changes if any
536
583
InterVersionedFile.get(other).method_name(parameters).
540
587
"""The available optimised InterVersionedFile types."""
542
589
def join(self, pb=None, msg=None, version_ids=None, ignore_missing=False):
563
610
target = temp_source
564
611
version_ids = self._get_source_version_ids(version_ids, ignore_missing)
565
612
graph = self.source.get_graph(version_ids)
566
order = topo_sort(graph.items())
613
order = tsort.topo_sort(graph.items())
567
614
pb = ui.ui_factory.nested_progress_bar()
568
615
parent_texts = {}
638
686
class InterVersionedFileTestProviderAdapter(object):
639
687
"""A tool to generate a suite testing multiple inter versioned-file classes.
641
This is done by copying the test once for each interversionedfile provider
689
This is done by copying the test once for each InterVersionedFile provider
642
690
and injecting the transport_server, transport_readonly_server,
643
691
versionedfile_factory and versionedfile_factory_to classes into each copy.
644
692
Each copy is also given a new id() to make it easy to identify.