~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

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

  • Committer: abentley
  • Date: 2006-04-20 23:47:53 UTC
  • mfrom: (1681 +trunk)
  • mto: This revision was merged to the branch mainline in revision 1683.
  • Revision ID: abentley@lappy-20060420234753-6a6874b76f09f86d
Merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 Canonical Ltd
 
1
# Copyright (C) 2005, 2006 Canonical Ltd
2
2
 
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
24
24
import urllib
25
25
 
26
26
from bzrlib.weavefile import read_weave, write_weave_v5
27
 
from bzrlib.weave import WeaveFile
28
 
from bzrlib.store import TransportStore, hash_prefix
 
27
from bzrlib.weave import WeaveFile, Weave
 
28
from bzrlib.store import TransportStore
29
29
from bzrlib.atomicfile import AtomicFile
30
30
from bzrlib.errors import NoSuchFile, FileExists
31
31
from bzrlib.symbol_versioning import *
32
32
from bzrlib.trace import mutter
 
33
import bzrlib.ui
33
34
 
34
35
 
35
36
class VersionedFileStore(TransportStore):
36
37
    """Collection of many versioned files in a transport."""
37
38
 
 
39
    # TODO: Rather than passing versionedfile_kwargs, perhaps pass in a
 
40
    # transport factory callable?
38
41
    def __init__(self, transport, prefixed=False, precious=False,
39
42
                 dir_mode=None, file_mode=None,
40
 
                 versionedfile_class=WeaveFile):
41
 
        super(WeaveStore, self).__init__(transport,
 
43
                 versionedfile_class=WeaveFile,
 
44
                 versionedfile_kwargs={},
 
45
                 escaped=False):
 
46
        super(VersionedFileStore, self).__init__(transport,
42
47
                dir_mode=dir_mode, file_mode=file_mode,
43
 
                prefixed=prefixed, compressed=False)
 
48
                prefixed=prefixed, compressed=False, escaped=escaped)
44
49
        self._precious = precious
45
50
        self._versionedfile_class = versionedfile_class
 
51
        self._versionedfile_kwargs = versionedfile_kwargs
46
52
 
47
53
    def _clear_cache_id(self, file_id, transaction):
48
54
        """WARNING may lead to inconsistent object references for file_id.
61
67
 
62
68
    def filename(self, file_id):
63
69
        """Return the path relative to the transport root."""
64
 
        if self._prefixed:
65
 
            return hash_prefix(file_id) + urllib.quote(file_id)
66
 
        else:
67
 
            return urllib.quote(file_id)
 
70
        return self._relpath(file_id)
68
71
 
69
72
    def __iter__(self):
70
73
        suffixes = self._versionedfile_class.get_suffixes()
72
75
        for relpath in self._iter_files_recursive():
73
76
            for suffix in suffixes:
74
77
                if relpath.endswith(suffix):
75
 
                    id = os.path.basename(relpath[:-len(suffix)])
76
 
                    if not id in ids:
77
 
                        yield id
78
 
                        ids.add(id)
 
78
                    # TODO: use standard remove_suffix function
 
79
                    escaped_id = os.path.basename(relpath[:-len(suffix)])
 
80
                    file_id = self._unescape(escaped_id)
 
81
                    if file_id not in ids:
 
82
                        ids.add(file_id)
 
83
                        yield file_id
 
84
                    break # only one suffix can match
79
85
 
80
86
    def has_id(self, fileid):
81
87
        suffixes = self._versionedfile_class.get_suffixes()
99
105
            self._transport.delete(filename + suffix)
100
106
        self._clear_cache_id(file_id, transaction)
101
107
 
 
108
    def _get(self, file_id):
 
109
        return self._transport.get(self.filename(file_id))
 
110
 
 
111
    def _put(self, file_id, f):
 
112
        fn = self.filename(file_id)
 
113
        try:
 
114
            return self._transport.put(fn, f, mode=self._file_mode)
 
115
        except NoSuchFile:
 
116
            if not self._prefixed:
 
117
                raise
 
118
            self._transport.mkdir(os.path.dirname(fn), mode=self._dir_mode)
 
119
            return self._transport.put(fn, f, mode=self._file_mode)
 
120
 
102
121
    def get_weave(self, file_id, transaction):
103
122
        weave = transaction.map.find_weave(file_id)
104
123
        if weave is not None:
105
124
            #mutter("cache hit in %s for %s", self, file_id)
106
125
            return weave
107
126
        if transaction.writeable():
108
 
            w = self._versionedfile_class(self.filename(file_id), self._transport, self._file_mode)
 
127
            w = self._versionedfile_class(self.filename(file_id), self._transport, self._file_mode,
 
128
                                          **self._versionedfile_kwargs)
109
129
            transaction.map.add_weave(file_id, w)
110
130
            transaction.register_dirty(w)
111
131
        else:
113
133
                                          self._transport,
114
134
                                          self._file_mode,
115
135
                                          create=False,
116
 
                                          access_mode='r')
 
136
                                          access_mode='r',
 
137
                                          **self._versionedfile_kwargs)
117
138
            transaction.map.add_weave(file_id, w)
118
139
            transaction.register_clean(w, precious=self._precious)
119
140
        return w
124
145
 
125
146
        Returned as a list of lines.
126
147
        """
127
 
        assert 0
128
148
        w = self.get_weave(file_id, transaction)
129
149
        return w.get_lines(rev_id)
130
150
    
140
160
        if self.has_id(file_id):
141
161
            self.delete(file_id, transaction)
142
162
        try:
143
 
            weave = self._versionedfile_class(self.filename(file_id), self._transport, self._file_mode, create=True)
 
163
            weave = self._versionedfile_class(self.filename(file_id), self._transport, self._file_mode, create=True,
 
164
                                              **self._versionedfile_kwargs)
144
165
        except NoSuchFile:
145
166
            if not self._prefixed:
146
167
                # unexpected error - NoSuchFile is raised on a missing dir only and that
147
168
                # only occurs when we are prefixed.
148
169
                raise
149
 
            self._transport.mkdir(hash_prefix(file_id), mode=self._dir_mode)
150
 
            weave = self._versionedfile_class(self.filename(file_id), self._transport, self._file_mode, create=True)
 
170
            self._transport.mkdir(self.hash_prefix(file_id), mode=self._dir_mode)
 
171
            weave = self._versionedfile_class(self.filename(file_id), self._transport, 
 
172
                                              self._file_mode, create=True,
 
173
                                              **self._versionedfile_kwargs)
151
174
        return weave
152
175
 
153
176
    def get_weave_or_empty(self, file_id, transaction):
167
190
        Its maintained for backwards compatability but will only work on
168
191
        weave stores - pre 0.8 repositories.
169
192
        """
170
 
        self._put_weave(self, file_id, weave, transaction)
 
193
        self._put_weave(file_id, weave, transaction)
171
194
 
172
195
    def _put_weave(self, file_id, weave, transaction):
173
196
        """Preserved here for upgrades-to-weaves to use."""
246
269
            # we are copying single objects, and there may be open tranasactions
247
270
            # so again with the passthrough
248
271
            to_transaction = PassThroughTransaction()
 
272
        pb = bzrlib.ui.ui_factory.nested_progress_bar()
249
273
        for count, f in enumerate(file_ids):
250
274
            mutter("copy weave {%s} into %s", f, self)
251
 
            if pb:
252
 
                pb.update('copy', count, len(file_ids))
 
275
            pb.update('copy', count, len(file_ids))
253
276
            # if we have it in cache, its faster.
254
277
            # joining is fast with knits, and bearable for weaves -
255
278
            # indeed the new case can be optimised if needed.
256
279
            target = self._make_new_versionedfile(f, to_transaction)
257
280
            target.join(from_store.get_weave(f, from_transaction))
258
 
        if pb:
259
 
            pb.clear()
 
281
        pb.finished()
260
282
 
261
283
    def total_size(self):
262
284
        count, bytes =  super(VersionedFileStore, self).total_size()