~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/versionedfile.py

  • Committer: Alexander Belchenko
  • Date: 2006-07-31 16:12:57 UTC
  • mto: (1711.2.111 jam-integration)
  • mto: This revision was merged to the branch mainline in revision 1906.
  • Revision ID: bialix@ukr.net-20060731161257-91a231523255332c
new official bzr.ico

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 by Canonical Ltd
 
1
# Copyright (C) 2005, 2006 by Canonical Ltd
2
2
#
3
3
# Authors:
4
4
#   Johan Rydberg <jrydberg@gnu.org>
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.
10
 
 
 
10
#
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.
15
 
 
 
15
#
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
19
19
 
20
 
# Remaing to do is to figure out if get_graph should return a simple
21
 
# map, or a graph object of some kind.
22
 
 
23
 
 
24
20
"""Versioned text file storage api."""
25
21
 
26
22
 
30
26
 
31
27
import bzrlib.errors as errors
32
28
from bzrlib.inter import InterObject
33
 
from bzrlib.symbol_versioning import *
34
29
from bzrlib.textmerge import TextMerge
35
30
from bzrlib.transport.memory import MemoryTransport
36
31
from bzrlib.tsort import topo_sort
37
32
from bzrlib import ui
 
33
from bzrlib.symbol_versioning import (deprecated_function,
 
34
        deprecated_method,
 
35
        zero_eight,
 
36
        )
38
37
 
39
38
 
40
39
class VersionedFile(object):
58
57
    def copy_to(self, name, transport):
59
58
        """Copy this versioned file to name on transport."""
60
59
        raise NotImplementedError(self.copy_to)
61
 
    
 
60
 
62
61
    @deprecated_method(zero_eight)
63
62
    def names(self):
64
63
        """Return a list of all the versions in this versioned file.
174
173
        if self._access_mode != 'w':
175
174
            raise errors.ReadOnlyObjectDirtiedError(self)
176
175
 
 
176
    def enable_cache(self):
 
177
        """Tell this versioned file that it should cache any data it reads.
 
178
        
 
179
        This is advisory, implementations do not have to support caching.
 
180
        """
 
181
        pass
 
182
    
177
183
    def clear_cache(self):
178
 
        """Remove any data cached in the versioned file object."""
 
184
        """Remove any data cached in the versioned file object.
 
185
 
 
186
        This only needs to be supported if caches are supported
 
187
        """
 
188
        pass
179
189
 
180
190
    def clone_text(self, new_version_id, old_version_id, parents):
181
191
        """Add an identical text to old_version_id as new_version_id.
256
266
        return ''.join(self.get_lines(version_id))
257
267
    get_string = get_text
258
268
 
 
269
    def get_texts(self, version_ids):
 
270
        """Return the texts of listed versions as a list of strings.
 
271
 
 
272
        Raises RevisionNotPresent if version is not present in
 
273
        file history.
 
274
        """
 
275
        return [''.join(self.get_lines(v)) for v in version_ids]
 
276
 
259
277
    def get_lines(self, version_id):
260
278
        """Return version contents as a sequence of lines.
261
279
 
286
304
        """
287
305
        raise NotImplementedError(self.get_ancestry_with_ghosts)
288
306
        
289
 
    def get_graph(self):
290
 
        """Return a graph for the entire versioned file.
 
307
    def get_graph(self, version_ids=None):
 
308
        """Return a graph from the versioned file. 
291
309
        
292
310
        Ghosts are not listed or referenced in the graph.
 
311
        :param version_ids: Versions to select.
 
312
                            None means retrieve all versions.
293
313
        """
294
314
        result = {}
295
 
        for version in self.versions():
296
 
            result[version] = self.get_parents(version)
 
315
        if version_ids is None:
 
316
            for version in self.versions():
 
317
                result[version] = self.get_parents(version)
 
318
        else:
 
319
            pending = set(version_ids)
 
320
            while pending:
 
321
                version = pending.pop()
 
322
                if version in result:
 
323
                    continue
 
324
                parents = self.get_parents(version)
 
325
                for parent in parents:
 
326
                    if parent in result:
 
327
                        continue
 
328
                    pending.add(parent)
 
329
                result[version] = parents
297
330
        return result
298
331
 
299
332
    def get_graph_with_ghosts(self):
377
410
        specific version marker at this point. The api may be changed
378
411
        during development to include the version that the versioned file
379
412
        thinks is relevant, but given that such hints are just guesses,
380
 
        its better not to have it if we dont need it.
 
413
        its better not to have it if we don't need it.
381
414
 
382
415
        NOTES: Lines are normalised: they will all have \n terminators.
383
416
               Lines are returned in arbitrary order.
472
505
       
473
506
        # We previously considered either 'unchanged' or 'killed-both' lines
474
507
        # to be possible places to resynchronize.  However, assuming agreement
475
 
        # on killed-both lines may be too agressive. -- mbp 20060324
 
508
        # on killed-both lines may be too aggressive. -- mbp 20060324
476
509
        for state, line in self.plan:
477
510
            if state == 'unchanged':
478
511
                # resync and flush queued conflicts changes if any
550
583
            # Make a new target-format versioned file. 
551
584
            temp_source = self.target.create_empty("temp", MemoryTransport())
552
585
            target = temp_source
553
 
        graph = self.source.get_graph()
 
586
        version_ids = self._get_source_version_ids(version_ids, ignore_missing)
 
587
        graph = self.source.get_graph(version_ids)
554
588
        order = topo_sort(graph.items())
555
589
        pb = ui.ui_factory.nested_progress_bar()
556
590
        parent_texts = {}
595
629
        finally:
596
630
            pb.finished()
597
631
 
 
632
    def _get_source_version_ids(self, version_ids, ignore_missing):
 
633
        """Determine the version ids to be used from self.source.
 
634
 
 
635
        :param version_ids: The caller-supplied version ids to check. (None 
 
636
                            for all). If None is in version_ids, it is stripped.
 
637
        :param ignore_missing: if True, remove missing ids from the version 
 
638
                               list. If False, raise RevisionNotPresent on
 
639
                               a missing version id.
 
640
        :return: A set of version ids.
 
641
        """
 
642
        if version_ids is None:
 
643
            # None cannot be in source.versions
 
644
            return set(self.source.versions())
 
645
        else:
 
646
            if ignore_missing:
 
647
                return set(self.source.versions()).intersection(set(version_ids))
 
648
            else:
 
649
                new_version_ids = set()
 
650
                for version in version_ids:
 
651
                    if version is None:
 
652
                        continue
 
653
                    if not self.source.has_version(version):
 
654
                        raise errors.RevisionNotPresent(version, str(self.source))
 
655
                    else:
 
656
                        new_version_ids.add(version)
 
657
                return new_version_ids
 
658
 
598
659
 
599
660
class InterVersionedFileTestProviderAdapter(object):
600
661
    """A tool to generate a suite testing multiple inter versioned-file classes.
601
662
 
602
 
    This is done by copying the test once for each interversionedfile provider
 
663
    This is done by copying the test once for each InterVersionedFile provider
603
664
    and injecting the transport_server, transport_readonly_server,
604
665
    versionedfile_factory and versionedfile_factory_to classes into each copy.
605
666
    Each copy is also given a new id() to make it easy to identify.
634
695
        from bzrlib.weave import WeaveFile
635
696
        from bzrlib.knit import KnitVersionedFile
636
697
        result = []
637
 
        # test the fallback InterVersionedFile from weave to annotated knits
 
698
        # test the fallback InterVersionedFile from annotated knits to weave
638
699
        result.append((InterVersionedFile, 
639
 
                       WeaveFile,
640
 
                       KnitVersionedFile))
 
700
                       KnitVersionedFile,
 
701
                       WeaveFile))
641
702
        for optimiser in InterVersionedFile._optimisers:
642
703
            result.append((optimiser,
643
 
                           optimiser._matching_file_factory,
644
 
                           optimiser._matching_file_factory
 
704
                           optimiser._matching_file_from_factory,
 
705
                           optimiser._matching_file_to_factory
645
706
                           ))
646
707
        # if there are specific combinations we want to use, we can add them 
647
708
        # here.