~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tree.py

Update news and readme

- better explanation of dependencies

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
from bzrlib.inventory import Inventory
27
27
from bzrlib.osutils import appendpath, fingerprint_file
28
28
 
 
29
 
 
30
exporters = {}
 
31
 
29
32
class Tree(object):
30
33
    """Abstract file tree.
31
34
 
68
71
    def id2path(self, file_id):
69
72
        return self.inventory.id2path(file_id)
70
73
 
71
 
    def kind(self, file_id):
72
 
        raise NotImplementedError("subclasses must implement kind")
73
 
 
74
74
    def _get_inventory(self):
75
75
        return self._inventory
76
76
    
104
104
        """Print file with id `file_id` to stdout."""
105
105
        import sys
106
106
        sys.stdout.write(self.get_file_text(file_id))
107
 
 
108
 
    def lock_read(self):
109
 
        pass
110
 
 
111
 
    def unlock(self):
112
 
        pass
113
 
 
114
 
    def filter_unversioned_files(self, paths):
115
 
        """Filter out paths that are not versioned.
116
 
 
117
 
        :return: set of paths.
118
 
        """
119
 
        # NB: we specifically *don't* call self.has_filename, because for
120
 
        # WorkingTrees that can indicate files that exist on disk but that 
121
 
        # are not versioned.
122
 
        pred = self.inventory.has_filename
123
 
        return set((p for p in paths if not pred(p)))
124
 
        
125
 
        
 
107
        
 
108
        
 
109
    def export(self, dest, format='dir', root=None):
 
110
        """Export this tree."""
 
111
        try:
 
112
            exporter = exporters[format]
 
113
        except KeyError:
 
114
            from bzrlib.errors import BzrCommandError
 
115
            raise BzrCommandError("export format %r not supported" % format)
 
116
        exporter(self, dest, root)
 
117
 
 
118
 
 
119
 
126
120
class RevisionTree(Tree):
127
121
    """Tree viewing a previous revision.
128
122
 
133
127
           or at least passing a description to the constructor.
134
128
    """
135
129
    
136
 
    def __init__(self, branch, inv, revision_id):
137
 
        self._branch = branch
138
 
        self._weave_store = branch.weave_store
 
130
    def __init__(self, weave_store, inv, revision_id):
 
131
        self._weave_store = weave_store
139
132
        self._inventory = inv
140
133
        self._revision_id = revision_id
141
134
 
142
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
143
139
        return self._weave_store.get_weave(file_id,
144
 
                self._branch.get_transaction())
 
140
            transactions.PassThroughTransaction())
 
141
 
145
142
 
146
143
    def get_file_lines(self, file_id):
147
144
        ie = self._inventory[file_id]
148
145
        weave = self.get_weave(file_id)
149
 
        return weave.get_lines(ie.revision)
 
146
        return weave.get(ie.revision)
 
147
        
150
148
 
151
149
    def get_file_text(self, file_id):
152
150
        return ''.join(self.get_file_lines(file_id))
153
151
 
 
152
 
154
153
    def get_file(self, file_id):
155
154
        return StringIO(self.get_file_text(file_id))
156
155
 
183
182
    def kind(self, file_id):
184
183
        return self._inventory[file_id].kind
185
184
 
186
 
    def lock_read(self):
187
 
        self._branch.lock_read()
188
 
 
189
 
    def unlock(self):
190
 
        self._branch.unlock()
191
 
 
192
 
 
193
185
class EmptyTree(Tree):
194
186
    def __init__(self):
195
187
        self._inventory = Inventory()
200
192
    def has_filename(self, filename):
201
193
        return False
202
194
 
203
 
    def kind(self, file_id):
204
 
        assert self._inventory[file_id].kind == "root_directory"
205
 
        return "root_directory"
206
 
 
207
195
    def list_files(self):
208
196
        return iter([])
209
197
    
281
269
            
282
270
 
283
271
 
 
272
######################################################################
 
273
# export
 
274
 
 
275
def dir_exporter(tree, dest, root):
 
276
    """Export this tree to a new directory.
 
277
 
 
278
    `dest` should not exist, and will be created holding the
 
279
    contents of this tree.
 
280
 
 
281
    TODO: To handle subdirectories we need to create the
 
282
           directories first.
 
283
 
 
284
    :note: If the export fails, the destination directory will be
 
285
           left in a half-assed state.
 
286
    """
 
287
    import os
 
288
    os.mkdir(dest)
 
289
    mutter('export version %r' % tree)
 
290
    inv = tree.inventory
 
291
    for dp, ie in inv.iter_entries():
 
292
        ie.put_on_disk(dest, dp, tree)
 
293
 
 
294
exporters['dir'] = dir_exporter
 
295
 
 
296
try:
 
297
    import tarfile
 
298
except ImportError:
 
299
    pass
 
300
else:
 
301
    def get_root_name(dest):
 
302
        """Get just the root name for a tarball.
 
303
 
 
304
        >>> get_root_name('mytar.tar')
 
305
        'mytar'
 
306
        >>> get_root_name('mytar.tar.bz2')
 
307
        'mytar'
 
308
        >>> get_root_name('tar.tar.tar.tgz')
 
309
        'tar.tar.tar'
 
310
        >>> get_root_name('bzr-0.0.5.tar.gz')
 
311
        'bzr-0.0.5'
 
312
        >>> get_root_name('a/long/path/mytar.tgz')
 
313
        'mytar'
 
314
        >>> get_root_name('../parent/../dir/other.tbz2')
 
315
        'other'
 
316
        """
 
317
        endings = ['.tar', '.tar.gz', '.tgz', '.tar.bz2', '.tbz2']
 
318
        dest = os.path.basename(dest)
 
319
        for end in endings:
 
320
            if dest.endswith(end):
 
321
                return dest[:-len(end)]
 
322
 
 
323
    def tar_exporter(tree, dest, root, compression=None):
 
324
        """Export this tree to a new tar file.
 
325
 
 
326
        `dest` will be created holding the contents of this tree; if it
 
327
        already exists, it will be clobbered, like with "tar -c".
 
328
        """
 
329
        from time import time
 
330
        now = time()
 
331
        compression = str(compression or '')
 
332
        if root is None:
 
333
            root = get_root_name(dest)
 
334
        try:
 
335
            ball = tarfile.open(dest, 'w:' + compression)
 
336
        except tarfile.CompressionError, e:
 
337
            raise BzrError(str(e))
 
338
        mutter('export version %r' % tree)
 
339
        inv = tree.inventory
 
340
        for dp, ie in inv.iter_entries():
 
341
            mutter("  export {%s} kind %s to %s" % (ie.file_id, ie.kind, dest))
 
342
            item, fileobj = ie.get_tar_item(root, dp, now, tree)
 
343
            ball.addfile(item, fileobj)
 
344
        ball.close()
 
345
 
 
346
    exporters['tar'] = tar_exporter
 
347
 
 
348
    def tgz_exporter(tree, dest, root):
 
349
        tar_exporter(tree, dest, root, compression='gz')
 
350
    exporters['tgz'] = tgz_exporter
 
351
 
 
352
    def tbz_exporter(tree, dest, root):
 
353
        tar_exporter(tree, dest, root, compression='bz2')
 
354
    exporters['tbz2'] = tbz_exporter