~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tree.py

  • Committer: Robert Collins
  • Date: 2005-08-25 01:13:32 UTC
  • mto: (974.1.50) (1185.1.10) (1092.3.1)
  • mto: This revision was merged to the branch mainline in revision 1139.
  • Revision ID: robertc@robertcollins.net-20050825011331-6d549d5de7edcec1
two bugfixes to smart_add - do not add paths from nested trees to the parent tree, and do not mutate the user supplied file list

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
"""
19
19
 
20
20
import os
21
 
from cStringIO import StringIO
22
21
 
23
22
import bzrlib
24
23
from bzrlib.trace import mutter, note
25
 
from bzrlib.errors import BzrError, BzrCheckError
 
24
from bzrlib.errors import BzrError
26
25
from bzrlib.inventory import Inventory
27
 
from bzrlib.osutils import appendpath, fingerprint_file
 
26
from bzrlib.osutils import pumpfile, appendpath, fingerprint_file
28
27
 
29
28
 
30
29
exporters = {}
58
57
    def has_id(self, file_id):
59
58
        return self.inventory.has_id(file_id)
60
59
 
61
 
    def has_or_had_id(self, file_id):
62
 
        if file_id == self.inventory.root.file_id:
63
 
            return True
64
 
        return self.inventory.has_id(file_id)
65
 
 
66
60
    __contains__ = has_id
67
61
 
68
62
    def __iter__(self):
81
75
                         doc="Inventory of this Tree")
82
76
 
83
77
    def _check_retrieved(self, ie, f):
84
 
        if not __debug__:
85
 
            return  
86
78
        fp = fingerprint_file(f)
87
79
        f.seek(0)
88
80
        
100
92
                     "store is probably damaged/corrupt"])
101
93
 
102
94
 
103
 
    def print_file(self, file_id):
104
 
        """Print file with id `file_id` to stdout."""
 
95
    def print_file(self, fileid):
 
96
        """Print file with id `fileid` to stdout."""
105
97
        import sys
106
 
        sys.stdout.write(self.get_file_text(file_id))
 
98
        pumpfile(self.get_file(fileid), sys.stdout)
107
99
        
108
100
        
109
101
    def export(self, dest, format='dir', root=None):
127
119
           or at least passing a description to the constructor.
128
120
    """
129
121
    
130
 
    def __init__(self, weave_store, inv, revision_id):
131
 
        self._weave_store = weave_store
 
122
    def __init__(self, store, inv):
 
123
        self._store = store
132
124
        self._inventory = inv
133
 
        self._revision_id = revision_id
134
 
 
135
 
    def get_weave(self, file_id):
136
 
        # FIXME: RevisionTree should be given a branch
137
 
        # not a store, or the store should know the branch.
138
 
        import bzrlib.transactions as transactions
139
 
        return self._weave_store.get_weave(file_id,
140
 
            transactions.PassThroughTransaction())
141
 
 
142
 
 
143
 
    def get_file_lines(self, file_id):
144
 
        ie = self._inventory[file_id]
145
 
        weave = self.get_weave(file_id)
146
 
        return weave.get(ie.revision)
147
 
        
148
 
 
149
 
    def get_file_text(self, file_id):
150
 
        return ''.join(self.get_file_lines(file_id))
151
 
 
152
125
 
153
126
    def get_file(self, file_id):
154
 
        return StringIO(self.get_file_text(file_id))
 
127
        ie = self._inventory[file_id]
 
128
        f = self._store[ie.text_id]
 
129
        mutter("  get fileid{%s} from %r" % (file_id, self))
 
130
        self._check_retrieved(ie, f)
 
131
        return f
155
132
 
156
133
    def get_file_size(self, file_id):
157
134
        return self._inventory[file_id].text_size
161
138
        if ie.kind == "file":
162
139
            return ie.text_sha1
163
140
 
164
 
    def is_executable(self, file_id):
165
 
        ie = self._inventory[file_id]
166
 
        if ie.kind != "file":
167
 
            return None 
168
 
        return self._inventory[file_id].executable
169
 
 
170
141
    def has_filename(self, filename):
171
142
        return bool(self.inventory.path2id(filename))
172
143
 
173
144
    def list_files(self):
174
145
        # The only files returned by this are those from the version
175
146
        for path, entry in self.inventory.iter_entries():
176
 
            yield path, 'V', entry.kind, entry.file_id, entry
177
 
 
178
 
    def get_symlink_target(self, file_id):
179
 
        ie = self._inventory[file_id]
180
 
        return ie.symlink_target;
181
 
 
182
 
    def kind(self, file_id):
183
 
        return self._inventory[file_id].kind
 
147
            yield path, 'V', entry.kind, entry.file_id
 
148
 
184
149
 
185
150
class EmptyTree(Tree):
186
151
    def __init__(self):
187
152
        self._inventory = Inventory()
188
153
 
189
 
    def get_symlink_target(self, file_id):
190
 
        return None
191
 
 
192
154
    def has_filename(self, filename):
193
155
        return False
194
156
 
195
157
    def list_files(self):
196
 
        return iter([])
 
158
        if False:  # just to make it a generator
 
159
            yield None
197
160
    
198
161
    def __contains__(self, file_id):
199
162
        return file_id in self._inventory
203
166
        return None
204
167
 
205
168
 
 
169
 
 
170
 
206
171
######################################################################
207
172
# diff
208
173
 
289
254
    mutter('export version %r' % tree)
290
255
    inv = tree.inventory
291
256
    for dp, ie in inv.iter_entries():
292
 
        ie.put_on_disk(dest, dp, tree)
293
 
 
 
257
        kind = ie.kind
 
258
        fullpath = appendpath(dest, dp)
 
259
        if kind == 'directory':
 
260
            os.mkdir(fullpath)
 
261
        elif kind == 'file':
 
262
            pumpfile(tree.get_file(ie.file_id), file(fullpath, 'wb'))
 
263
        else:
 
264
            raise BzrError("don't know how to export {%s} of kind %r" % (ie.file_id, kind))
 
265
        mutter("  export {%s} kind %s to %s" % (ie.file_id, kind, fullpath))
294
266
exporters['dir'] = dir_exporter
295
267
 
296
268
try:
339
311
        inv = tree.inventory
340
312
        for dp, ie in inv.iter_entries():
341
313
            mutter("  export {%s} kind %s to %s" % (ie.file_id, ie.kind, dest))
342
 
            item, fileobj = ie.get_tar_item(root, dp, now, tree)
 
314
            item = tarfile.TarInfo(os.path.join(root, dp))
 
315
            # TODO: would be cool to actually set it to the timestamp of the
 
316
            # revision it was last changed
 
317
            item.mtime = now
 
318
            if ie.kind == 'directory':
 
319
                item.type = tarfile.DIRTYPE
 
320
                fileobj = None
 
321
                item.name += '/'
 
322
                item.size = 0
 
323
                item.mode = 0755
 
324
            elif ie.kind == 'file':
 
325
                item.type = tarfile.REGTYPE
 
326
                fileobj = tree.get_file(ie.file_id)
 
327
                item.size = _find_file_size(fileobj)
 
328
                item.mode = 0644
 
329
            else:
 
330
                raise BzrError("don't know how to export {%s} of kind %r" %
 
331
                        (ie.file_id, ie.kind))
 
332
 
343
333
            ball.addfile(item, fileobj)
344
334
        ball.close()
345
 
 
346
335
    exporters['tar'] = tar_exporter
347
336
 
348
337
    def tgz_exporter(tree, dest, root):
352
341
    def tbz_exporter(tree, dest, root):
353
342
        tar_exporter(tree, dest, root, compression='bz2')
354
343
    exporters['tbz2'] = tbz_exporter
 
344
 
 
345
 
 
346
def _find_file_size(fileobj):
 
347
    offset = fileobj.tell()
 
348
    try:
 
349
        fileobj.seek(0, 2)
 
350
        size = fileobj.tell()
 
351
    except TypeError:
 
352
        # gzip doesn't accept second argument to seek()
 
353
        fileobj.seek(0)
 
354
        size = 0
 
355
        while True:
 
356
            nread = len(fileobj.read())
 
357
            if nread == 0:
 
358
                break
 
359
            size += nread
 
360
    fileobj.seek(offset)
 
361
    return size