~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tree.py

  • Committer: Robert Collins
  • Date: 2005-10-11 02:52:47 UTC
  • mfrom: (1417.1.13)
  • Revision ID: robertc@robertcollins.net-20051011025247-4b95466bb6509385
merge in revision-history caching, and tuning of fetch to not retrieve more data than needed when nothing needs to be pulled

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
"""Tree classes, representing directory at point in time.
18
18
"""
19
19
 
20
 
from osutils import pumpfile, appendpath, fingerprint_file
21
20
import os
 
21
from cStringIO import StringIO
22
22
 
 
23
import bzrlib
23
24
from bzrlib.trace import mutter, note
24
 
from bzrlib.errors import BzrError
 
25
from bzrlib.errors import BzrError, BzrCheckError
 
26
from bzrlib.inventory import Inventory
 
27
from bzrlib.osutils import appendpath, fingerprint_file
25
28
 
26
 
import bzrlib
27
29
 
28
30
exporters = {}
29
31
 
66
68
 
67
69
    def _get_inventory(self):
68
70
        return self._inventory
 
71
    
 
72
    def get_file_by_path(self, path):
 
73
        return self.get_file(self._inventory.path2id(path))
69
74
 
70
75
    inventory = property(_get_inventory,
71
76
                         doc="Inventory of this Tree")
72
77
 
73
78
    def _check_retrieved(self, ie, f):
 
79
        if not __debug__:
 
80
            return  
74
81
        fp = fingerprint_file(f)
75
82
        f.seek(0)
76
83
        
88
95
                     "store is probably damaged/corrupt"])
89
96
 
90
97
 
91
 
    def print_file(self, fileid):
92
 
        """Print file with id `fileid` to stdout."""
 
98
    def print_file(self, file_id):
 
99
        """Print file with id `file_id` to stdout."""
93
100
        import sys
94
 
        pumpfile(self.get_file(fileid), sys.stdout)
 
101
        sys.stdout.write(self.get_file_text(file_id))
95
102
        
96
103
        
97
104
    def export(self, dest, format='dir', root=None):
115
122
           or at least passing a description to the constructor.
116
123
    """
117
124
    
118
 
    def __init__(self, store, inv):
119
 
        self._store = store
 
125
    def __init__(self, weave_store, inv, revision_id):
 
126
        self._weave_store = weave_store
120
127
        self._inventory = inv
 
128
        self._revision_id = revision_id
 
129
 
 
130
    def get_weave(self, file_id):
 
131
        # FIXME: RevisionTree should be given a branch
 
132
        # not a store, or the store should know the branch.
 
133
        import bzrlib.transactions as transactions
 
134
        return self._weave_store.get_weave(file_id,
 
135
            transactions.PassThroughTransaction())
 
136
 
 
137
 
 
138
    def get_file_lines(self, file_id):
 
139
        ie = self._inventory[file_id]
 
140
        weave = self.get_weave(file_id)
 
141
        return weave.get(ie.revision)
 
142
        
 
143
 
 
144
    def get_file_text(self, file_id):
 
145
        return ''.join(self.get_file_lines(file_id))
 
146
 
121
147
 
122
148
    def get_file(self, file_id):
123
 
        ie = self._inventory[file_id]
124
 
        f = self._store[ie.text_id]
125
 
        mutter("  get fileid{%s} from %r" % (file_id, self))
126
 
        self._check_retrieved(ie, f)
127
 
        return f
 
149
        return StringIO(self.get_file_text(file_id))
128
150
 
129
151
    def get_file_size(self, file_id):
130
152
        return self._inventory[file_id].text_size
131
153
 
132
154
    def get_file_sha1(self, file_id):
133
155
        ie = self._inventory[file_id]
134
 
        return ie.text_sha1
 
156
        if ie.kind == "file":
 
157
            return ie.text_sha1
 
158
 
 
159
    def is_executable(self, file_id):
 
160
        return self._inventory[file_id].executable
135
161
 
136
162
    def has_filename(self, filename):
137
163
        return bool(self.inventory.path2id(filename))
139
165
    def list_files(self):
140
166
        # The only files returned by this are those from the version
141
167
        for path, entry in self.inventory.iter_entries():
142
 
            yield path, 'V', entry.kind, entry.file_id
 
168
            yield path, 'V', entry.kind, entry.file_id, entry
 
169
 
 
170
    def get_symlink_target(self, file_id):
 
171
        ie = self._inventory[file_id]
 
172
        return ie.symlink_target;
143
173
 
144
174
 
145
175
class EmptyTree(Tree):
146
 
    def __init__(self, root_id):
147
 
        from bzrlib.inventory import Inventory
148
 
        self._inventory = Inventory(root_id)
 
176
    def __init__(self):
 
177
        self._inventory = Inventory()
 
178
 
 
179
    def get_symlink_target(self, file_id):
 
180
        return None
149
181
 
150
182
    def has_filename(self, filename):
151
183
        return False
152
184
 
153
185
    def list_files(self):
154
 
        if False:  # just to make it a generator
155
 
            yield None
 
186
        return iter([])
156
187
    
 
188
    def __contains__(self, file_id):
 
189
        return file_id in self._inventory
 
190
 
 
191
    def get_file_sha1(self, file_id):
 
192
        assert self._inventory[file_id].kind == "root_directory"
 
193
        return None
157
194
 
158
195
 
159
196
######################################################################
242
279
    mutter('export version %r' % tree)
243
280
    inv = tree.inventory
244
281
    for dp, ie in inv.iter_entries():
245
 
        kind = ie.kind
246
 
        fullpath = appendpath(dest, dp)
247
 
        if kind == 'directory':
248
 
            os.mkdir(fullpath)
249
 
        elif kind == 'file':
250
 
            pumpfile(tree.get_file(ie.file_id), file(fullpath, 'wb'))
251
 
        else:
252
 
            raise BzrError("don't know how to export {%s} of kind %r" % (ie.file_id, kind))
253
 
        mutter("  export {%s} kind %s to %s" % (ie.file_id, kind, fullpath))
 
282
        ie.put_on_disk(dest, dp, tree)
 
283
 
254
284
exporters['dir'] = dir_exporter
255
285
 
256
286
try:
299
329
        inv = tree.inventory
300
330
        for dp, ie in inv.iter_entries():
301
331
            mutter("  export {%s} kind %s to %s" % (ie.file_id, ie.kind, dest))
302
 
            item = tarfile.TarInfo(os.path.join(root, dp))
303
 
            # TODO: would be cool to actually set it to the timestamp of the
304
 
            # revision it was last changed
305
 
            item.mtime = now
306
 
            if ie.kind == 'directory':
307
 
                item.type = tarfile.DIRTYPE
308
 
                fileobj = None
309
 
                item.name += '/'
310
 
                item.size = 0
311
 
                item.mode = 0755
312
 
            elif ie.kind == 'file':
313
 
                item.type = tarfile.REGTYPE
314
 
                fileobj = tree.get_file(ie.file_id)
315
 
                item.size = _find_file_size(fileobj)
316
 
                item.mode = 0644
317
 
            else:
318
 
                raise BzrError("don't know how to export {%s} of kind %r" %
319
 
                        (ie.file_id, ie.kind))
320
 
 
 
332
            item, fileobj = ie.get_tar_item(root, dp, now, tree)
321
333
            ball.addfile(item, fileobj)
322
334
        ball.close()
 
335
 
323
336
    exporters['tar'] = tar_exporter
324
337
 
325
338
    def tgz_exporter(tree, dest, root):
329
342
    def tbz_exporter(tree, dest, root):
330
343
        tar_exporter(tree, dest, root, compression='bz2')
331
344
    exporters['tbz2'] = tbz_exporter
332
 
 
333
 
 
334
 
def _find_file_size(fileobj):
335
 
    offset = fileobj.tell()
336
 
    try:
337
 
        fileobj.seek(0, 2)
338
 
        size = fileobj.tell()
339
 
    except TypeError:
340
 
        # gzip doesn't accept second argument to seek()
341
 
        fileobj.seek(0)
342
 
        size = 0
343
 
        while True:
344
 
            nread = len(fileobj.read())
345
 
            if nread == 0:
346
 
                break
347
 
            size += nread
348
 
    fileobj.seek(offset)
349
 
    return size