~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/store/versioned/weave.py

  • Committer: Robert Collins
  • Date: 2006-03-01 08:40:35 UTC
  • mto: (1594.2.4 integration)
  • mto: This revision was merged to the branch mainline in revision 1596.
  • Revision ID: robertc@robertcollins.net-20060301084035-ce00abd11fe4da31
Change weave store to be a versioned store, using WeaveFiles which maintain integrity without needing explicit 'put' operations.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
import urllib
27
27
 
28
28
from bzrlib.weavefile import read_weave, write_weave_v5
29
 
from bzrlib.weave import Weave
 
29
from bzrlib.weave import Weave, WeaveFile
30
30
from bzrlib.store import TransportStore, hash_prefix
31
31
from bzrlib.atomicfile import AtomicFile
32
32
from bzrlib.errors import NoSuchFile, FileExists
 
33
from bzrlib.symbol_versioning import *
33
34
from bzrlib.trace import mutter
34
35
 
35
36
 
81
82
        if weave:
82
83
            mutter("cache hit in %s for %s", self, file_id)
83
84
            return weave
84
 
        w = read_weave(self._get(file_id))
 
85
        w = WeaveFile(self.filename(file_id), self._transport, self._file_mode)
85
86
        transaction.map.add_weave(file_id, w)
86
87
        transaction.register_clean(w, precious=self._precious)
87
88
        # TODO: jam 20051219 This should check if there is a prelude
97
98
        if weave:
98
99
            mutter("cache hit in %s for %s", self, weave_id)
99
100
            return weave
100
 
        # We want transactions to also cache preludes if that
101
 
        # is all that we are loading. So we need a unique
102
 
        # identifier, so that someone who wants the whole text
103
 
        # won't get just the prelude
104
 
        weave_id = 'PRELUDE-' + file_id
105
 
        weave = transaction.map.find_weave(weave_id)
106
 
        if weave:
107
 
            mutter("cache hit in %s for %s", self, weave_id)
108
 
            return weave
109
101
        w = read_weave(self._get(file_id), prelude=True)
110
 
        transaction.map.add_weave(weave_id, w)
111
 
        transaction.register_clean(w, precious=self._precious)
 
102
        # no point caching the prelude: any repeat action will need the real 
 
103
        # thing
112
104
        return w
113
105
 
114
106
    def get_lines(self, file_id, rev_id, transaction):
124
116
        try:
125
117
            return self.get_weave_prelude(file_id, transaction)
126
118
        except NoSuchFile:
127
 
            # We can cache here, because we know that there
128
 
            # is no complete object, since we got NoSuchFile
129
 
            weave = Weave(weave_name=file_id)
130
 
            transaction.map.add_weave(file_id, weave)
131
 
            transaction.register_clean(weave, precious=self._precious)
132
 
            return weave
 
119
            # returns more than needed - harmless as its empty.
 
120
            return self._new_weave(file_id, transaction)
 
121
 
 
122
    def _new_weave(self, file_id, transaction):
 
123
        """Make a new weave for file_id and return it."""
 
124
        weave = WeaveFile(self.filename(file_id), self._transport, self._file_mode)
 
125
        # ensure that the directories are created.
 
126
        # this is so that weave does not encounter ENOTDIR etc.
 
127
        weave_stream = self._weave_to_stream(weave)
 
128
        self._put(file_id, weave_stream)
 
129
        transaction.map.add_weave(file_id, weave)
 
130
        transaction.register_clean(weave, precious=self._precious)
 
131
        return weave
133
132
 
134
133
    def get_weave_or_empty(self, file_id, transaction):
135
134
        """Return a weave, or an empty one if it doesn't exist.""" 
136
135
        try:
137
136
            return self.get_weave(file_id, transaction)
138
137
        except NoSuchFile:
139
 
            weave = Weave(weave_name=file_id)
140
 
            transaction.map.add_weave(file_id, weave)
141
 
            transaction.register_clean(weave, precious=self._precious)
142
 
            return weave
 
138
            return self._new_weave(file_id, transaction)
143
139
 
 
140
    @deprecated_method(zero_eight)
144
141
    def put_weave(self, file_id, weave, transaction):
145
 
        """Write back a modified weave"""
 
142
        """This is a deprecated API: It writes an entire collection of ids out.
 
143
        
 
144
        This became inappropriate when we made a versioned file api which
 
145
        tracks the state of the collection of versions for a single id.
 
146
        
 
147
        Its maintained for backwards compatability but will only work on
 
148
        weave stores - pre 0.8 repositories.
 
149
        """
 
150
        self._put_weave(self, file_id, weave, transaction)
 
151
 
 
152
    def _put_weave(self, file_id, weave, transaction):
 
153
        """Preserved here for upgrades-to-weaves to use."""
146
154
        transaction.register_dirty(weave)
147
 
        # TODO FOR WRITE TRANSACTIONS: this should be done in a callback
148
 
        # from the transaction, when it decides to save.
 
155
        weave_stream = self._weave_to_stream(weave)
 
156
        self._put(file_id, weave_stream)
 
157
 
 
158
    def _weave_to_stream(self, weave):
 
159
        """Make a stream from a weave."""
149
160
        sio = StringIO()
150
161
        write_weave_v5(weave, sio)
151
162
        sio.seek(0)
152
 
        self._put(file_id, sio)
 
163
        return sio
153
164
 
 
165
    @deprecated_method(zero_eight)
154
166
    def add_text(self, file_id, rev_id, new_lines, parents, transaction):
155
 
        w = self.get_weave_or_empty(file_id, transaction)
156
 
        w.add_lines(rev_id, parents, new_lines)
157
 
        self.put_weave(file_id, w, transaction)
 
167
        """This method was a shorthand for 
 
168
 
 
169
        vfile = self.get_weave_or_empty(file_id, transaction)
 
170
        vfile.add_lines(rev_id, parents, new_lines)
 
171
        """
 
172
        vfile = self.get_weave_or_empty(file_id, transaction)
 
173
        vfile.add_lines(rev_id, parents, new_lines)
158
174
        
 
175
    @deprecated_method(zero_eight)
159
176
    def add_identical_text(self, file_id, old_rev_id, new_rev_id, parents,
160
177
                           transaction):
161
 
        w = self.get_weave_or_empty(file_id, transaction)
162
 
        parent_idxs = map(w.lookup, parents)
163
 
        w.add_identical(old_rev_id, new_rev_id, parent_idxs)
164
 
        self.put_weave(file_id, w, transaction)
 
178
        """This method was a shorthand for
 
179
 
 
180
        vfile = self.get_weave_or_empty(file_id, transaction)
 
181
        vfile.clone_text(new_rev_id, old_rev_id, parents)
 
182
        """
 
183
        vfile = self.get_weave_or_empty(file_id, transaction)
 
184
        vfile.clone_text(new_rev_id, old_rev_id, parents)
165
185
     
166
 
    def copy_multi(self, from_store, file_ids, pb=None):
 
186
    def copy_multi(self, from_store, file_ids, pb=None, from_transaction=None):
167
187
        assert isinstance(from_store, WeaveStore)
168
188
        for count, f in enumerate(file_ids):
169
189
            mutter("copy weave {%s} into %s", f, self)
170
190
            if pb:
171
191
                pb.update('copy', count, len(file_ids))
172
 
            self._put(f, from_store._get(f))
 
192
            # if we have it in cache, its faster.
 
193
            if from_transaction and from_transaction.map.find_weave(f):
 
194
                mutter("cache hit in %s for %s", from_store, f)
 
195
                weave = from_transaction.map.find_weave(f)
 
196
                weave_stream = self._weave_to_stream(weave)
 
197
                self._put(f, weave_stream)
 
198
            else:
 
199
                self._put(f, from_store._get(f))
173
200
        if pb:
174
201
            pb.clear()