~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-06 22:15:52 UTC
  • mfrom: (1185.13.2)
  • mto: This revision was merged to the branch mainline in revision 1420.
  • Revision ID: robertc@robertcollins.net-20051006221552-9b15c96fa504e0ad
mergeĀ fromĀ upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
# files whose id differs only in case.  That should probably be forbidden.
21
21
 
22
22
 
 
23
from cStringIO import StringIO
 
24
import os
23
25
import errno
24
 
import os
25
 
from cStringIO import StringIO
26
 
import urllib
27
26
 
28
27
from bzrlib.weavefile import read_weave, write_weave_v5
29
28
from bzrlib.weave import Weave
30
 
from bzrlib.store import TransportStore, hash_prefix
 
29
from bzrlib.store import Store
31
30
from bzrlib.atomicfile import AtomicFile
32
 
from bzrlib.errors import NoSuchFile, FileExists
 
31
from bzrlib.errors import NoSuchFile
33
32
from bzrlib.trace import mutter
34
33
 
35
34
 
36
 
class WeaveStore(TransportStore):
 
35
class WeaveStore(Store):
37
36
    """Collection of several weave files in a directory.
38
37
 
39
38
    This has some shortcuts for reading and writing them.
40
39
    """
41
40
    FILE_SUFFIX = '.weave'
42
41
 
43
 
    def __init__(self, transport, prefixed=False, precious=False,
44
 
                 dir_mode=None, file_mode=None):
45
 
        super(WeaveStore, self).__init__(transport,
46
 
                dir_mode=dir_mode, file_mode=file_mode,
47
 
                prefixed=prefixed, compressed=False)
48
 
        self._precious = precious
 
42
    def __init__(self, transport):
 
43
        self._transport = transport
 
44
        self._cache = {}
 
45
        self.enable_cache = False
 
46
 
49
47
 
50
48
    def filename(self, file_id):
51
49
        """Return the path relative to the transport root."""
52
 
        if self._prefixed:
53
 
            return hash_prefix(file_id) + urllib.quote(file_id) + WeaveStore.FILE_SUFFIX
54
 
        else:
55
 
            return urllib.quote(file_id) + WeaveStore.FILE_SUFFIX
 
50
        return file_id + WeaveStore.FILE_SUFFIX
56
51
 
57
52
    def __iter__(self):
58
53
        l = len(WeaveStore.FILE_SUFFIX)
59
 
        for relpath in self._iter_files_recursive():
60
 
            if relpath.endswith(WeaveStore.FILE_SUFFIX):
61
 
                yield os.path.basename(relpath[:-l])
 
54
        for f in self._transport.list_dir('.'):
 
55
            if f.endswith(WeaveStore.FILE_SUFFIX):
 
56
                f = f[:-l]
 
57
                yield f
62
58
 
63
 
    def has_id(self, fileid):
 
59
    def __contains__(self, fileid):
 
60
        """"""
64
61
        return self._transport.has(self.filename(fileid))
65
62
 
66
63
    def _get(self, file_id):
67
64
        return self._transport.get(self.filename(file_id))
68
65
 
69
66
    def _put(self, file_id, f):
70
 
        if self._prefixed:
71
 
            try:
72
 
                self._transport.mkdir(hash_prefix(file_id), mode=self._dir_mode)
73
 
            except FileExists:
74
 
                pass
75
 
        return self._transport.put(self.filename(file_id), f, mode=self._file_mode)
 
67
        return self._transport.put(self.filename(file_id), f)
76
68
 
77
 
    def get_weave(self, file_id, transaction):
78
 
        weave = transaction.map.find_weave(file_id)
79
 
        if weave:
80
 
            mutter("cache hit in %s for %s", self, file_id)
81
 
            return weave
 
69
    def get_weave(self, file_id):
 
70
        if self.enable_cache:
 
71
            if file_id in self._cache:
 
72
                mutter("cache hit in %s for %s", self, file_id)
 
73
                return self._cache[file_id]
82
74
        w = read_weave(self._get(file_id))
83
 
        transaction.map.add_weave(file_id, w)
84
 
        transaction.register_clean(w, precious=self._precious)
85
 
        # TODO: jam 20051219 This should check if there is a prelude
86
 
        #       which is already cached, and if so, should remove it
87
 
        #       But transaction doesn't seem to have a 'remove'
88
 
        #       One workaround would be to re-add the object with
89
 
        #       the PRELUDE marker.
90
 
        return w
91
 
 
92
 
    def get_weave_prelude(self, file_id, transaction):
93
 
        weave_id = file_id
94
 
        weave = transaction.map.find_weave(weave_id)
95
 
        if weave:
96
 
            mutter("cache hit in %s for %s", self, weave_id)
97
 
            return weave
98
 
        # We want transactions to also cache preludes if that
99
 
        # is all that we are loading. So we need a unique
100
 
        # identifier, so that someone who wants the whole text
101
 
        # won't get just the prelude
102
 
        weave_id = 'PRELUDE-' + file_id
103
 
        weave = transaction.map.find_weave(weave_id)
104
 
        if weave:
105
 
            mutter("cache hit in %s for %s", self, weave_id)
106
 
            return weave
107
 
        w = read_weave(self._get(file_id), prelude=True)
108
 
        transaction.map.add_weave(weave_id, w)
109
 
        transaction.register_clean(w, precious=self._precious)
110
 
        return w
111
 
 
112
 
    def get_lines(self, file_id, rev_id, transaction):
 
75
        if self.enable_cache:
 
76
            self._cache[file_id] = w
 
77
        return w
 
78
 
 
79
 
 
80
    def get_lines(self, file_id, rev_id):
113
81
        """Return text from a particular version of a weave.
114
82
 
115
83
        Returned as a list of lines."""
116
 
        w = self.get_weave(file_id, transaction)
 
84
        w = self.get_weave(file_id)
117
85
        return w.get(w.lookup(rev_id))
118
86
    
119
 
    def get_weave_prelude_or_empty(self, file_id, transaction):
120
 
        """cheap version that reads the prelude but not the lines
121
 
        """
122
 
        try:
123
 
            return self.get_weave_prelude(file_id, transaction)
124
 
        except NoSuchFile:
125
 
            # We can cache here, because we know that there
126
 
            # is no complete object, since we got NoSuchFile
127
 
            weave = Weave(weave_name=file_id)
128
 
            transaction.map.add_weave(file_id, weave)
129
 
            transaction.register_clean(weave, precious=self._precious)
130
 
            return weave
131
87
 
132
 
    def get_weave_or_empty(self, file_id, transaction):
 
88
    def get_weave_or_empty(self, file_id):
133
89
        """Return a weave, or an empty one if it doesn't exist.""" 
134
90
        try:
135
 
            return self.get_weave(file_id, transaction)
 
91
            inf = self._get(file_id)
136
92
        except NoSuchFile:
137
 
            weave = Weave(weave_name=file_id)
138
 
            transaction.map.add_weave(file_id, weave)
139
 
            transaction.register_clean(weave, precious=self._precious)
140
 
            return weave
 
93
            return Weave(weave_name=file_id)
 
94
        else:
 
95
            return read_weave(inf)
 
96
    
141
97
 
142
 
    def put_weave(self, file_id, weave, transaction):
 
98
    def put_weave(self, file_id, weave):
143
99
        """Write back a modified weave"""
144
 
        transaction.register_dirty(weave)
145
 
        # TODO FOR WRITE TRANSACTIONS: this should be done in a callback
146
 
        # from the transaction, when it decides to save.
 
100
        if self.enable_cache:
 
101
            self._cache[file_id] = weave
 
102
 
147
103
        sio = StringIO()
148
104
        write_weave_v5(weave, sio)
149
105
        sio.seek(0)
 
106
 
150
107
        self._put(file_id, sio)
151
108
 
152
 
    def add_text(self, file_id, rev_id, new_lines, parents, transaction):
153
 
        w = self.get_weave_or_empty(file_id, transaction)
 
109
 
 
110
    def add_text(self, file_id, rev_id, new_lines, parents):
 
111
        w = self.get_weave_or_empty(file_id)
154
112
        parent_idxs = map(w.lookup, parents)
155
113
        w.add(rev_id, parent_idxs, new_lines)
156
 
        self.put_weave(file_id, w, transaction)
 
114
        self.put_weave(file_id, w)
157
115
        
158
 
    def add_identical_text(self, file_id, old_rev_id, new_rev_id, parents,
159
 
                           transaction):
160
 
        w = self.get_weave_or_empty(file_id, transaction)
 
116
    def add_identical_text(self, file_id, old_rev_id, new_rev_id, parents):
 
117
        w = self.get_weave_or_empty(file_id)
161
118
        parent_idxs = map(w.lookup, parents)
162
119
        w.add_identical(old_rev_id, new_rev_id, parent_idxs)
163
 
        self.put_weave(file_id, w, transaction)
 
120
        self.put_weave(file_id, w)
164
121
     
165
122
    def copy_multi(self, from_store, file_ids):
166
123
        assert isinstance(from_store, WeaveStore)