~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tree.py

  • Committer: Martin Pool
  • Date: 2005-07-11 03:40:02 UTC
  • Revision ID: mbp@sourcefrog.net-20050711034002-575d84b4c7514542
- commit command refuses unless something is changed or --unchanged is given

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
20
21
import os
21
 
from cStringIO import StringIO
 
22
 
 
23
from bzrlib.trace import mutter, note
 
24
from bzrlib.errors import BzrError
22
25
 
23
26
import bzrlib
24
 
from bzrlib.trace import mutter, note
25
 
from bzrlib.errors import BzrError, BzrCheckError
26
 
from bzrlib.inventory import Inventory
27
 
from bzrlib.osutils import appendpath, fingerprint_file
28
 
 
29
27
 
30
28
exporters = {}
31
29
 
68
66
 
69
67
    def _get_inventory(self):
70
68
        return self._inventory
71
 
    
72
 
    def get_file_by_path(self, path):
73
 
        return self.get_file(self._inventory.path2id(path))
74
69
 
75
70
    inventory = property(_get_inventory,
76
71
                         doc="Inventory of this Tree")
77
72
 
78
73
    def _check_retrieved(self, ie, f):
79
 
        if not __debug__:
80
 
            return  
81
74
        fp = fingerprint_file(f)
82
75
        f.seek(0)
83
76
        
95
88
                     "store is probably damaged/corrupt"])
96
89
 
97
90
 
98
 
    def print_file(self, file_id):
99
 
        """Print file with id `file_id` to stdout."""
 
91
    def print_file(self, fileid):
 
92
        """Print file with id `fileid` to stdout."""
100
93
        import sys
101
 
        sys.stdout.write(self.get_file_text(file_id))
 
94
        pumpfile(self.get_file(fileid), sys.stdout)
102
95
        
103
96
        
104
97
    def export(self, dest, format='dir', root=None):
122
115
           or at least passing a description to the constructor.
123
116
    """
124
117
    
125
 
    def __init__(self, weave_store, inv, revision_id):
126
 
        self._weave_store = weave_store
 
118
    def __init__(self, store, inv):
 
119
        self._store = store
127
120
        self._inventory = inv
128
 
        self._revision_id = revision_id
129
 
 
130
 
    def get_weave(self, file_id):
131
 
        return self._weave_store.get_weave(file_id)
132
 
 
133
 
 
134
 
    def get_file_lines(self, file_id):
135
 
        ie = self._inventory[file_id]
136
 
        weave = self.get_weave(file_id)
137
 
        return weave.get(ie.revision)
138
 
        
139
 
 
140
 
    def get_file_text(self, file_id):
141
 
        return ''.join(self.get_file_lines(file_id))
142
 
 
143
121
 
144
122
    def get_file(self, file_id):
145
 
        return StringIO(self.get_file_text(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
146
128
 
147
129
    def get_file_size(self, file_id):
148
130
        return self._inventory[file_id].text_size
149
131
 
150
132
    def get_file_sha1(self, file_id):
151
133
        ie = self._inventory[file_id]
152
 
        if ie.kind == "file":
153
 
            return ie.text_sha1
154
 
 
155
 
    def is_executable(self, file_id):
156
 
        return self._inventory[file_id].executable
 
134
        return ie.text_sha1
157
135
 
158
136
    def has_filename(self, filename):
159
137
        return bool(self.inventory.path2id(filename))
161
139
    def list_files(self):
162
140
        # The only files returned by this are those from the version
163
141
        for path, entry in self.inventory.iter_entries():
164
 
            yield path, 'V', entry.kind, entry.file_id, entry
165
 
 
166
 
    def get_symlink_target(self, file_id):
167
 
        ie = self._inventory[file_id]
168
 
        return ie.symlink_target;
 
142
            yield path, 'V', entry.kind, entry.file_id
169
143
 
170
144
 
171
145
class EmptyTree(Tree):
172
146
    def __init__(self):
 
147
        from bzrlib.inventory import Inventory
173
148
        self._inventory = Inventory()
174
149
 
175
 
    def get_symlink_target(self, file_id):
176
 
        return None
177
 
 
178
150
    def has_filename(self, filename):
179
151
        return False
180
152
 
181
153
    def list_files(self):
182
 
        return iter([])
 
154
        if False:  # just to make it a generator
 
155
            yield None
183
156
    
184
 
    def __contains__(self, file_id):
185
 
        return file_id in self._inventory
186
 
 
187
 
    def get_file_sha1(self, file_id):
188
 
        assert self._inventory[file_id].kind == "root_directory"
189
 
        return None
190
157
 
191
158
 
192
159
######################################################################
275
242
    mutter('export version %r' % tree)
276
243
    inv = tree.inventory
277
244
    for dp, ie in inv.iter_entries():
278
 
        ie.put_on_disk(dest, dp, tree)
279
 
 
 
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))
280
254
exporters['dir'] = dir_exporter
281
255
 
282
256
try:
325
299
        inv = tree.inventory
326
300
        for dp, ie in inv.iter_entries():
327
301
            mutter("  export {%s} kind %s to %s" % (ie.file_id, ie.kind, dest))
328
 
            item, fileobj = ie.get_tar_item(root, dp, now, tree)
 
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
 
329
321
            ball.addfile(item, fileobj)
330
322
        ball.close()
331
 
 
332
323
    exporters['tar'] = tar_exporter
333
324
 
334
325
    def tgz_exporter(tree, dest, root):
338
329
    def tbz_exporter(tree, dest, root):
339
330
        tar_exporter(tree, dest, root, compression='bz2')
340
331
    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