~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/store/weave.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2006-02-21 17:41:02 UTC
  • mfrom: (1185.50.85 bzr-jam-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20060221174102-aa6bd4464296c614
Mac OSX raises EPERM when you try to unlink a directory

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
import errno
 
24
import os
23
25
from cStringIO import StringIO
24
 
import os
25
 
import errno
 
26
import urllib
26
27
 
27
28
from bzrlib.weavefile import read_weave, write_weave_v5
28
29
from bzrlib.weave import Weave
39
40
    """
40
41
    FILE_SUFFIX = '.weave'
41
42
 
42
 
    def __init__(self, transport, prefixed=False, precious=False):
43
 
        self._transport = transport
44
 
        self._prefixed = prefixed
 
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)
45
48
        self._precious = precious
46
49
 
47
50
    def filename(self, file_id):
48
51
        """Return the path relative to the transport root."""
49
52
        if self._prefixed:
50
 
            return hash_prefix(file_id) + file_id + WeaveStore.FILE_SUFFIX
 
53
            return hash_prefix(file_id) + urllib.quote(file_id) + WeaveStore.FILE_SUFFIX
51
54
        else:
52
 
            return file_id + WeaveStore.FILE_SUFFIX
 
55
            return urllib.quote(file_id) + WeaveStore.FILE_SUFFIX
53
56
 
54
57
    def __iter__(self):
55
58
        l = len(WeaveStore.FILE_SUFFIX)
56
 
        for relpath, st in self._iter_relpaths():
 
59
        for relpath in self._iter_files_recursive():
57
60
            if relpath.endswith(WeaveStore.FILE_SUFFIX):
58
61
                yield os.path.basename(relpath[:-l])
59
62
 
60
 
    def __contains__(self, fileid):
61
 
        """"""
 
63
    def has_id(self, fileid):
62
64
        return self._transport.has(self.filename(fileid))
63
65
 
64
66
    def _get(self, file_id):
65
67
        return self._transport.get(self.filename(file_id))
66
68
 
67
69
    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)
 
70
        # less round trips to mkdir on failure than mkdir always
 
71
        try:
 
72
            return self._transport.put(self.filename(file_id), f, mode=self._file_mode)
 
73
        except NoSuchFile:
 
74
            if not self._prefixed:
 
75
                raise
 
76
            self._transport.mkdir(hash_prefix(file_id), mode=self._dir_mode)
 
77
            return self._transport.put(self.filename(file_id), f, mode=self._file_mode)
74
78
 
75
79
    def get_weave(self, file_id, transaction):
76
80
        weave = transaction.map.find_weave(file_id)
80
84
        w = read_weave(self._get(file_id))
81
85
        transaction.map.add_weave(file_id, w)
82
86
        transaction.register_clean(w, precious=self._precious)
 
87
        # TODO: jam 20051219 This should check if there is a prelude
 
88
        #       which is already cached, and if so, should remove it
 
89
        #       But transaction doesn't seem to have a 'remove'
 
90
        #       One workaround would be to re-add the object with
 
91
        #       the PRELUDE marker.
 
92
        return w
 
93
 
 
94
    def get_weave_prelude(self, file_id, transaction):
 
95
        weave_id = file_id
 
96
        weave = transaction.map.find_weave(weave_id)
 
97
        if weave:
 
98
            mutter("cache hit in %s for %s", self, weave_id)
 
99
            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
        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)
83
112
        return w
84
113
 
85
114
    def get_lines(self, file_id, rev_id, transaction):
89
118
        w = self.get_weave(file_id, transaction)
90
119
        return w.get(w.lookup(rev_id))
91
120
    
 
121
    def get_weave_prelude_or_empty(self, file_id, transaction):
 
122
        """cheap version that reads the prelude but not the lines
 
123
        """
 
124
        try:
 
125
            return self.get_weave_prelude(file_id, transaction)
 
126
        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
 
133
 
92
134
    def get_weave_or_empty(self, file_id, transaction):
93
135
        """Return a weave, or an empty one if it doesn't exist.""" 
94
136
        try:
122
164
        w.add_identical(old_rev_id, new_rev_id, parent_idxs)
123
165
        self.put_weave(file_id, w, transaction)
124
166
     
125
 
    def copy_multi(self, from_store, file_ids):
 
167
    def copy_multi(self, from_store, file_ids, pb=None):
126
168
        assert isinstance(from_store, WeaveStore)
127
 
        for f in file_ids:
 
169
        for count, f in enumerate(file_ids):
128
170
            mutter("copy weave {%s} into %s", f, self)
 
171
            if pb:
 
172
                pb.update('copy', count, len(file_ids))
129
173
            self._put(f, from_store._get(f))
 
174
        if pb:
 
175
            pb.clear()