/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/export/__init__.py

Merge bzr.dev, update to use new hooks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
"""Export functionality, which can take a Tree and create a different representation.
18
 
 
19
 
Such as non-controlled directories, tarfiles, zipfiles, etc.
 
17
"""Export trees to tarballs, non-controlled directories, zipfiles, etc.
20
18
"""
21
19
 
22
20
import os
 
21
import time
 
22
import warnings
 
23
 
23
24
from bzrlib import (
24
25
    errors,
25
26
    pyutils,
 
27
    trace,
26
28
    )
27
29
 
28
30
# Maps format name => export function
30
32
# Maps filename extensions => export format name
31
33
_exporter_extensions = {}
32
34
 
 
35
 
33
36
def register_exporter(format, extensions, func, override=False):
34
37
    """Register an exporter.
35
38
 
57
60
 
58
61
    When requesting a specific type of export, load the respective path.
59
62
    """
60
 
    def _loader(tree, dest, root, subdir, filtered, per_file_timestamps):
 
63
    def _loader(tree, dest, root, subdir, force_mtime, fileobj):
61
64
        func = pyutils.get_named_object(module, funcname)
62
 
        return func(tree, dest, root, subdir, filtered=filtered,
63
 
                    per_file_timestamps=per_file_timestamps)
 
65
        return func(tree, dest, root, subdir, force_mtime=force_mtime,
 
66
            fileobj=fileobj)
 
67
 
64
68
    register_exporter(scheme, extensions, _loader)
65
69
 
66
70
 
67
 
def export(tree, dest, format=None, root=None, subdir=None, filtered=False,
68
 
           per_file_timestamps=False):
69
 
    """Export the given Tree to the specific destination.
 
71
def get_export_generator(tree, dest=None, format=None, root=None, subdir=None,
 
72
                         filtered=False, per_file_timestamps=False,
 
73
                         fileobj=None):
 
74
    """Returns a generator that exports the given tree.
 
75
 
 
76
    The generator is expected to yield None while exporting the tree while the
 
77
    actual export is written to ``fileobj``.
70
78
 
71
79
    :param tree: A Tree (such as RevisionTree) to export
72
 
    :param dest: The destination where the files,etc should be put
 
80
 
 
81
    :param dest: The destination where the files, etc should be put
 
82
 
73
83
    :param format: The format (dir, zip, etc), if None, it will check the
74
 
                   extension on dest, looking for a match
75
 
    :param root: The root location inside the format.
76
 
                 It is common practise to have zipfiles and tarballs
77
 
                 extract into a subdirectory, rather than into the
78
 
                 current working directory.
79
 
                 If root is None, the default root will be
80
 
                 selected as the destination without its
81
 
                 extension.
 
84
        extension on dest, looking for a match
 
85
 
 
86
    :param root: The root location inside the format.  It is common practise to
 
87
        have zipfiles and tarballs extract into a subdirectory, rather than
 
88
        into the current working directory.  If root is None, the default root
 
89
        will be selected as the destination without its extension.
 
90
 
82
91
    :param subdir: A starting directory within the tree. None means to export
83
92
        the entire tree, and anything else should specify the relative path to
84
93
        a directory to start exporting from.
85
 
    :param filtered: If True, content filtering is applied to the
86
 
                     files exported.
87
 
    :param per_file_timestamps: Whether to use the timestamp stored in the 
88
 
        tree rather than now(). This will do a revision lookup 
89
 
        for every file so will be significantly slower.
 
94
 
 
95
    :param filtered: If True, content filtering is applied to the exported
 
96
        files.  Deprecated in favour of passing a ContentFilterTree
 
97
        as the source.
 
98
 
 
99
    :param per_file_timestamps: Whether to use the timestamp stored in the tree
 
100
        rather than now(). This will do a revision lookup for every file so
 
101
        will be significantly slower.
 
102
 
 
103
    :param fileobj: Optional file object to use
90
104
    """
91
105
    global _exporters, _exporter_extensions
92
106
 
93
 
    if format is None:
 
107
    if format is None and dest is not None:
94
108
        for ext in _exporter_extensions:
95
109
            if dest.endswith(ext):
96
110
                format = _exporter_extensions[ext]
103
117
 
104
118
    if format not in _exporters:
105
119
        raise errors.NoSuchExportFormat(format)
 
120
 
 
121
    if not per_file_timestamps:
 
122
        force_mtime = time.time()
 
123
    else:
 
124
        force_mtime = None
 
125
 
 
126
    trace.mutter('export version %r', tree)
 
127
 
 
128
    if filtered:
 
129
        from bzrlib.filter_tree import ContentFilterTree
 
130
        warnings.warn(
 
131
            "passing filtered=True to export is deprecated in bzr 2.4",
 
132
            stacklevel=2)
 
133
        tree = ContentFilterTree(tree, tree._content_filter_stack)
 
134
        # We don't want things re-filtered by the specific exporter.
 
135
        filtered = False
 
136
 
106
137
    tree.lock_read()
107
138
    try:
108
 
        return _exporters[format](tree, dest, root, subdir, filtered=filtered,
109
 
                                  per_file_timestamps=per_file_timestamps)
 
139
        for _ in _exporters[format](
 
140
            tree, dest, root, subdir,
 
141
            force_mtime=force_mtime, fileobj=fileobj):
 
142
            yield
110
143
    finally:
111
144
        tree.unlock()
112
145
 
113
146
 
 
147
def export(tree, dest, format=None, root=None, subdir=None, filtered=False,
 
148
           per_file_timestamps=False, fileobj=None):
 
149
    """Export the given Tree to the specific destination.
 
150
 
 
151
    :param tree: A Tree (such as RevisionTree) to export
 
152
    :param dest: The destination where the files,etc should be put
 
153
    :param format: The format (dir, zip, etc), if None, it will check the
 
154
                   extension on dest, looking for a match
 
155
    :param root: The root location inside the format.
 
156
                 It is common practise to have zipfiles and tarballs
 
157
                 extract into a subdirectory, rather than into the
 
158
                 current working directory.
 
159
                 If root is None, the default root will be
 
160
                 selected as the destination without its
 
161
                 extension.
 
162
    :param subdir: A starting directory within the tree. None means to export
 
163
        the entire tree, and anything else should specify the relative path to
 
164
        a directory to start exporting from.
 
165
    :param filtered: If True, content filtering is applied to the
 
166
        files exported.  Deprecated in favor of passing an ContentFilterTree.
 
167
    :param per_file_timestamps: Whether to use the timestamp stored in the
 
168
        tree rather than now(). This will do a revision lookup
 
169
        for every file so will be significantly slower.
 
170
    :param fileobj: Optional file object to use
 
171
    """
 
172
    for _ in get_export_generator(tree, dest, format, root, subdir, filtered,
 
173
                                  per_file_timestamps, fileobj):
 
174
        pass
 
175
 
 
176
 
114
177
def get_root_name(dest):
115
178
    """Get just the root name for an export.
116
179
 
117
 
    >>> get_root_name('../mytest.tar')
118
 
    'mytest'
119
 
    >>> get_root_name('mytar.tar')
120
 
    'mytar'
121
 
    >>> get_root_name('mytar.tar.bz2')
122
 
    'mytar'
123
 
    >>> get_root_name('tar.tar.tar.tgz')
124
 
    'tar.tar.tar'
125
 
    >>> get_root_name('bzr-0.0.5.tar.gz')
126
 
    'bzr-0.0.5'
127
 
    >>> get_root_name('bzr-0.0.5.zip')
128
 
    'bzr-0.0.5'
129
 
    >>> get_root_name('bzr-0.0.5')
130
 
    'bzr-0.0.5'
131
 
    >>> get_root_name('a/long/path/mytar.tgz')
132
 
    'mytar'
133
 
    >>> get_root_name('../parent/../dir/other.tbz2')
134
 
    'other'
135
180
    """
136
181
    global _exporter_extensions
 
182
    if dest == '-':
 
183
        # Exporting to -/foo doesn't make sense so use relative paths.
 
184
        return ''
137
185
    dest = os.path.basename(dest)
138
186
    for ext in _exporter_extensions:
139
187
        if dest.endswith(ext):
141
189
    return dest
142
190
 
143
191
 
144
 
def _export_iter_entries(tree, subdir):
 
192
def _export_iter_entries(tree, subdir, skip_special=True):
145
193
    """Iter the entries for tree suitable for exporting.
146
194
 
147
195
    :param tree: A tree object.
148
196
    :param subdir: None or the path of an entry to start exporting from.
 
197
    :param skip_special: Whether to skip .bzr files.
 
198
    :return: iterator over tuples with final path, tree path and inventory
 
199
        entry for each entry to export
149
200
    """
150
 
    inv = tree.inventory
151
 
    if subdir is None:
152
 
        subdir_object = None
153
 
    else:
154
 
        subdir_id = inv.path2id(subdir)
155
 
        if subdir_id is not None:
156
 
            subdir_object = inv[subdir_id]
157
 
        # XXX: subdir is path not an id, so NoSuchId isn't proper error
158
 
        else:
159
 
            raise errors.NoSuchId(tree, subdir)
160
 
    if subdir_object is not None and subdir_object.kind != 'directory':
161
 
        yield subdir_object.name, subdir_object
162
 
        return
163
 
    else:
164
 
        entries = inv.iter_entries(subdir_object)
165
 
    if subdir is None:
166
 
        entries.next() # skip root
167
 
    for entry in entries:
 
201
    if subdir == '':
 
202
        subdir = None
 
203
    if subdir is not None:
 
204
        subdir = subdir.rstrip('/')
 
205
    entries = tree.iter_entries_by_dir()
 
206
    entries.next()  # skip root
 
207
    for path, entry in entries:
168
208
        # The .bzr* namespace is reserved for "magic" files like
169
209
        # .bzrignore and .bzrrules - do not export these
170
 
        if entry[0].startswith(".bzr"):
 
210
        if skip_special and path.startswith(".bzr"):
171
211
            continue
172
 
        if subdir is None:
173
 
            if not tree.has_filename(entry[0]):
 
212
        if path == subdir:
 
213
            if entry.kind == 'directory':
 
214
                continue
 
215
            final_path = entry.name
 
216
        elif subdir is not None:
 
217
            if path.startswith(subdir + '/'):
 
218
                final_path = path[len(subdir) + 1:]
 
219
            else:
174
220
                continue
175
221
        else:
176
 
            if not tree.has_filename(os.path.join(subdir, entry[0])):
177
 
                continue
178
 
        yield entry
179
 
 
180
 
 
181
 
register_lazy_exporter(None, [], 'bzrlib.export.dir_exporter', 'dir_exporter')
182
 
register_lazy_exporter('dir', [], 'bzrlib.export.dir_exporter', 'dir_exporter')
183
 
register_lazy_exporter('tar', ['.tar'], 'bzrlib.export.tar_exporter', 'tar_exporter')
184
 
register_lazy_exporter('tgz', ['.tar.gz', '.tgz'], 'bzrlib.export.tar_exporter', 'tgz_exporter')
185
 
register_lazy_exporter('tbz2', ['.tar.bz2', '.tbz2'], 'bzrlib.export.tar_exporter', 'tbz_exporter')
186
 
register_lazy_exporter('zip', ['.zip'], 'bzrlib.export.zip_exporter', 'zip_exporter')
187
 
 
 
222
            final_path = path
 
223
        if not tree.has_filename(path):
 
224
            continue
 
225
 
 
226
        yield final_path, path, entry
 
227
 
 
228
 
 
229
register_lazy_exporter(None, [], 'bzrlib.export.dir_exporter',
 
230
                       'dir_exporter_generator')
 
231
register_lazy_exporter('dir', [], 'bzrlib.export.dir_exporter',
 
232
                       'dir_exporter_generator')
 
233
register_lazy_exporter('tar', ['.tar'], 'bzrlib.export.tar_exporter',
 
234
                       'plain_tar_exporter_generator')
 
235
register_lazy_exporter('tgz', ['.tar.gz', '.tgz'],
 
236
                       'bzrlib.export.tar_exporter',
 
237
                       'tgz_exporter_generator')
 
238
register_lazy_exporter('tbz2', ['.tar.bz2', '.tbz2'],
 
239
                       'bzrlib.export.tar_exporter', 'tbz_exporter_generator')
 
240
register_lazy_exporter('tlzma', ['.tar.lzma'], 'bzrlib.export.tar_exporter',
 
241
                       'tar_lzma_exporter_generator')
 
242
register_lazy_exporter('txz', ['.tar.xz'], 'bzrlib.export.tar_exporter',
 
243
                       'tar_xz_exporter_generator')
 
244
register_lazy_exporter('zip', ['.zip'], 'bzrlib.export.zip_exporter',
 
245
                       'zip_exporter_generator')