~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/store/weave.py

  • Committer: Robert Collins
  • Date: 2005-10-21 04:02:58 UTC
  • mto: This revision was merged to the branch mainline in revision 1503.
  • Revision ID: robertc@robertcollins.net-20051021040258-84a5db1be67b30b9
make build-api have a hasbang

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
# along with this program; if not, write to the Free Software
17
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
18
 
19
 
# Author: Martin Pool <mbp@canonical.com>
20
 
 
21
 
 
 
19
# XXX: Some consideration of the problems that might occur if there are
 
20
# files whose id differs only in case.  That should probably be forbidden.
 
21
 
 
22
 
 
23
from cStringIO import StringIO
22
24
import os
23
 
import bzrlib.weavefile
24
 
 
25
 
 
26
 
class WeaveStore(object):
27
 
    """Collection of several weave files."""
28
 
    def __init__(self, dir):
29
 
        self._dir = dir
30
 
 
31
 
 
32
 
    def get_weave(self, file_id):
33
 
        path = self._dir + os.sep + file_id + '.weave'
34
 
        return bzrlib.weavefile.read_weave(file(path, 'rb'))
 
25
import errno
 
26
 
 
27
from bzrlib.weavefile import read_weave, write_weave_v5
 
28
from bzrlib.weave import Weave
 
29
from bzrlib.store import TransportStore, hash_prefix
 
30
from bzrlib.atomicfile import AtomicFile
 
31
from bzrlib.errors import NoSuchFile, FileExists
 
32
from bzrlib.trace import mutter
 
33
 
 
34
 
 
35
class WeaveStore(TransportStore):
 
36
    """Collection of several weave files in a directory.
 
37
 
 
38
    This has some shortcuts for reading and writing them.
 
39
    """
 
40
    FILE_SUFFIX = '.weave'
 
41
 
 
42
    def __init__(self, transport, prefixed=False, precious=False):
 
43
        self._transport = transport
 
44
        self._prefixed = prefixed
 
45
        self._precious = precious
 
46
 
 
47
    def filename(self, file_id):
 
48
        """Return the path relative to the transport root."""
 
49
        if self._prefixed:
 
50
            return hash_prefix(file_id) + file_id + WeaveStore.FILE_SUFFIX
 
51
        else:
 
52
            return file_id + WeaveStore.FILE_SUFFIX
 
53
 
 
54
    def __iter__(self):
 
55
        l = len(WeaveStore.FILE_SUFFIX)
 
56
        for relpath, st in self._iter_relpaths():
 
57
            if relpath.endswith(WeaveStore.FILE_SUFFIX):
 
58
                yield os.path.basename(relpath[:-l])
 
59
 
 
60
    def __contains__(self, fileid):
 
61
        """"""
 
62
        return self._transport.has(self.filename(fileid))
 
63
 
 
64
    def _get(self, file_id):
 
65
        return self._transport.get(self.filename(file_id))
 
66
 
 
67
    def _put(self, file_id, f):
 
68
        if self._prefixed:
 
69
            try:
 
70
                self._transport.mkdir(hash_prefix(file_id))
 
71
            except FileExists:
 
72
                pass
 
73
        return self._transport.put(self.filename(file_id), f)
 
74
 
 
75
    def get_weave(self, file_id, transaction):
 
76
        weave = transaction.map.find_weave(file_id)
 
77
        if weave:
 
78
            mutter("cache hit in %s for %s", self, file_id)
 
79
            return weave
 
80
        w = read_weave(self._get(file_id))
 
81
        transaction.map.add_weave(file_id, w)
 
82
        transaction.register_clean(w, precious=self._precious)
 
83
        return w
 
84
 
 
85
    def get_lines(self, file_id, rev_id, transaction):
 
86
        """Return text from a particular version of a weave.
 
87
 
 
88
        Returned as a list of lines."""
 
89
        w = self.get_weave(file_id, transaction)
 
90
        return w.get(w.lookup(rev_id))
35
91
    
 
92
    def get_weave_or_empty(self, file_id, transaction):
 
93
        """Return a weave, or an empty one if it doesn't exist.""" 
 
94
        try:
 
95
            return self.get_weave(file_id, transaction)
 
96
        except NoSuchFile:
 
97
            weave = Weave(weave_name=file_id)
 
98
            transaction.map.add_weave(file_id, weave)
 
99
            transaction.register_clean(weave, precious=self._precious)
 
100
            return weave
 
101
 
 
102
    def put_weave(self, file_id, weave, transaction):
 
103
        """Write back a modified weave"""
 
104
        transaction.register_dirty(weave)
 
105
        # TODO FOR WRITE TRANSACTIONS: this should be done in a callback
 
106
        # from the transaction, when it decides to save.
 
107
        sio = StringIO()
 
108
        write_weave_v5(weave, sio)
 
109
        sio.seek(0)
 
110
        self._put(file_id, sio)
 
111
 
 
112
    def add_text(self, file_id, rev_id, new_lines, parents, transaction):
 
113
        w = self.get_weave_or_empty(file_id, transaction)
 
114
        parent_idxs = map(w.lookup, parents)
 
115
        w.add(rev_id, parent_idxs, new_lines)
 
116
        self.put_weave(file_id, w, transaction)
 
117
        
 
118
    def add_identical_text(self, file_id, old_rev_id, new_rev_id, parents,
 
119
                           transaction):
 
120
        w = self.get_weave_or_empty(file_id, transaction)
 
121
        parent_idxs = map(w.lookup, parents)
 
122
        w.add_identical(old_rev_id, new_rev_id, parent_idxs)
 
123
        self.put_weave(file_id, w, transaction)
 
124
     
 
125
    def copy_multi(self, from_store, file_ids):
 
126
        assert isinstance(from_store, WeaveStore)
 
127
        for f in file_ids:
 
128
            mutter("copy weave {%s} into %s", f, self)
 
129
            self._put(f, from_store._get(f))