~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/store/text.py

  • Committer: Robert Collins
  • Date: 2005-10-09 23:42:12 UTC
  • Revision ID: robertc@robertcollins.net-20051009234212-7973344d900afb0b
merge in niemeyers prefixed-store patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
import os, tempfile
25
25
 
26
26
import bzrlib.store
 
27
from bzrlib.store import hash_prefix
27
28
from bzrlib.trace import mutter
28
 
from bzrlib.errors import BzrError
 
29
from bzrlib.errors import BzrError, FileExists
29
30
 
30
31
from cStringIO import StringIO
31
 
from stat import ST_SIZE
 
32
from stat import ST_SIZE, ST_MODE, S_ISDIR
32
33
 
33
34
 
34
35
class TextStore(bzrlib.store.TransportStore):
41
42
    Files are stored uncompressed, with no delta compression.
42
43
    """
43
44
 
44
 
    def __init__(self, transport):
 
45
    def __init__(self, transport, prefixed=False):
45
46
        super(TextStore, self).__init__(transport)
 
47
        self._prefixed = prefixed
46
48
 
47
49
    def _check_fileid(self, fileid):
48
50
        if not isinstance(fileid, basestring):
52
54
 
53
55
    def _relpath(self, fileid):
54
56
        self._check_fileid(fileid)
55
 
        return fileid
 
57
        if self._prefixed:
 
58
            return hash_prefix(fileid) + fileid
 
59
        else:
 
60
            return fileid
56
61
 
57
62
    def add(self, f, fileid):
58
63
        """Add contents of a file into the store.
65
70
        if self._transport.has(fn):
66
71
            raise BzrError("store %r already contains id %r" % (self._transport.base, fileid))
67
72
 
 
73
        if self._prefixed:
 
74
            try:
 
75
                self._transport.mkdir(hash_prefix(fileid))
 
76
            except FileExists:
 
77
                pass
 
78
 
68
79
        self._transport.put(fn, f)
69
80
 
70
 
    def _do_copy(self, other, to_copy, pb, permit_failure=False):
71
 
        if isinstance(other, TextStore):
72
 
            return self._copy_multi_text(other, to_copy, pb,
73
 
                    permit_failure=permit_failure)
74
 
        return super(TextStore, self)._do_copy(other, to_copy,
75
 
                pb, permit_failure=permit_failure)
76
 
 
77
 
    def _copy_multi_text(self, other, to_copy, pb,
78
 
            permit_failure=False):
79
 
        # Because of _transport, we can no longer assume
80
 
        # that they are on the same filesystem, we can, however
81
 
        # assume that we only need to copy the exact bytes,
82
 
        # we don't need to process the files.
83
 
 
84
 
        failed = set()
85
 
        if permit_failure:
86
 
            new_to_copy = set()
87
 
            for fileid, has in zip(to_copy, other.has(to_copy)):
88
 
                if has:
89
 
                    new_to_copy.add(fileid)
90
 
                else:
91
 
                    failed.add(fileid)
92
 
            to_copy = new_to_copy
93
 
            #mutter('_copy_multi_text copying %s, failed %s' % (to_copy, failed))
94
 
 
95
 
        paths = [self._relpath(fileid) for fileid in to_copy]
96
 
        count = other._transport.copy_to(paths, self._transport, pb=pb)
97
 
        assert count == len(to_copy)
98
 
        return count, failed
99
 
 
100
81
    def __contains__(self, fileid):
101
82
        """"""
102
83
        fn = self._relpath(fileid)
156
137
            yield None
157
138
            count += 1
158
139
 
 
140
    def _iter_relpaths(self):
 
141
        transport = self._transport
 
142
        queue = list(transport.list_dir('.'))
 
143
        while queue:
 
144
            relpath = queue.pop(0)
 
145
            st = transport.stat(relpath)
 
146
            if S_ISDIR(st[ST_MODE]):
 
147
                for i, basename in enumerate(transport.list_dir(relpath)):
 
148
                    queue.insert(i, relpath+'/'+basename)
 
149
            else:
 
150
                yield relpath, st
 
151
 
159
152
    def __iter__(self):
160
 
        # TODO: case-insensitive?
161
 
        for f in self._transport.list_dir('.'):
162
 
            yield f
 
153
        for relpath, st in self._iter_relpaths():
 
154
            yield os.path.basename(relpath)
163
155
 
164
156
    def __len__(self):
165
 
        return len([f for f in self._transport.list_dir('.')])
166
 
 
 
157
        return len(list(self._iter_relpath()))
167
158
 
168
159
    def __getitem__(self, fileid):
169
160
        """Returns a file reading from a particular entry."""
184
175
        the content."""
185
176
        total = 0
186
177
        count = 0
187
 
        relpaths = [self._relpath(fid) for fid in self]
188
 
        for st in self._transport.stat_multi(relpaths):
 
178
        for relpath, st in self._iter_relpaths():
189
179
            count += 1
190
180
            total += st[ST_SIZE]
191
181