~bzr-pqm/bzr/bzr.dev

5809.3.2 by Aaron Bentley
Support PreviewTree.has_filename.
1
# Copyright (C) 2005-2011 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
16
5967.6.1 by Martin Pool
pep8 cleanup
17
"""Export trees to tarballs, non-controlled directories, zipfiles, etc.
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
18
"""
19
20
import os
5718.5.1 by Jelmer Vernooij
per_file_timestamp -> force_mtime.
21
import time
6006.3.6 by Martin Pool
Deprecate export(filtered=True)
22
import warnings
23
5436.2.1 by Andrew Bennetts
Add bzrlib.pyutils, which has get_named_object, a wrapper around __import__.
24
from bzrlib import (
25
    errors,
26
    pyutils,
5718.5.4 by Jelmer Vernooij
fix timestamp in tgz files.
27
    trace,
5436.2.1 by Andrew Bennetts
Add bzrlib.pyutils, which has get_named_object, a wrapper around __import__.
28
    )
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
29
30
# Maps format name => export function
31
_exporters = {}
32
# Maps filename extensions => export format name
33
_exporter_extensions = {}
34
5967.6.1 by Martin Pool
pep8 cleanup
35
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
36
def register_exporter(format, extensions, func, override=False):
37
    """Register an exporter.
38
39
    :param format: This is the name of the format, such as 'tgz' or 'zip'
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
40
    :param extensions: Extensions which should be used in the case that a
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
41
                       format was not explicitly specified.
42
    :type extensions: List
43
    :param func: The function. It will be called with (tree, dest, root)
44
    :param override: Whether to override an object which already exists.
45
                     Frequently plugins will want to provide functionality
46
                     until it shows up in mainline, so the default is False.
47
    """
48
    global _exporters, _exporter_extensions
49
1963.2.1 by Robey Pointer
remove usage of has_key()
50
    if (format not in _exporters) or override:
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
51
        _exporters[format] = func
52
53
    for ext in extensions:
1963.2.1 by Robey Pointer
remove usage of has_key()
54
        if (ext not in _exporter_extensions) or override:
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
55
            _exporter_extensions[ext] = format
56
57
58
def register_lazy_exporter(scheme, extensions, module, funcname):
59
    """Register lazy-loaded exporter function.
60
61
    When requesting a specific type of export, load the respective path.
62
    """
6006.3.7 by Martin Pool
Remove duplicated content-filtering code from exporters
63
    def _loader(tree, dest, root, subdir, force_mtime, fileobj):
5436.2.1 by Andrew Bennetts
Add bzrlib.pyutils, which has get_named_object, a wrapper around __import__.
64
        func = pyutils.get_named_object(module, funcname)
6006.3.7 by Martin Pool
Remove duplicated content-filtering code from exporters
65
        return func(tree, dest, root, subdir, force_mtime=force_mtime,
66
            fileobj=fileobj)
5967.6.1 by Martin Pool
pep8 cleanup
67
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
68
    register_exporter(scheme, extensions, _loader)
5967.6.1 by Martin Pool
pep8 cleanup
69
70
5952.1.18 by geoffreyfishing at gmail
Fixed line ending problems.
71
def get_export_generator(tree, dest=None, format=None, root=None, subdir=None,
5952.2.1 by Vincent Ladeuil
PEP8 tweaks, lines too long, spaces at end of lines.
72
                         filtered=False, per_file_timestamps=False,
73
                         fileobj=None):
74
    """Returns a generator that exports the given tree.
5967.6.1 by Martin Pool
pep8 cleanup
75
5952.2.1 by Vincent Ladeuil
PEP8 tweaks, lines too long, spaces at end of lines.
76
    The generator is expected to yield None while exporting the tree while the
77
    actual export is written to ``fileobj``.
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
78
79
    :param tree: A Tree (such as RevisionTree) to export
5952.2.1 by Vincent Ladeuil
PEP8 tweaks, lines too long, spaces at end of lines.
80
81
    :param dest: The destination where the files, etc should be put
82
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
83
    :param format: The format (dir, zip, etc), if None, it will check the
5952.2.1 by Vincent Ladeuil
PEP8 tweaks, lines too long, spaces at end of lines.
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
3613.2.1 by Robert Collins
Teach export how to export a subdirectory. (Robert Collins)
91
    :param subdir: A starting directory within the tree. None means to export
92
        the entire tree, and anything else should specify the relative path to
93
        a directory to start exporting from.
5952.2.1 by Vincent Ladeuil
PEP8 tweaks, lines too long, spaces at end of lines.
94
95
    :param filtered: If True, content filtering is applied to the exported
6006.3.6 by Martin Pool
Deprecate export(filtered=True)
96
        files.  Deprecated in favour of passing a ContentFilterTree
97
        as the source.
5952.2.1 by Vincent Ladeuil
PEP8 tweaks, lines too long, spaces at end of lines.
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
5952.1.6 by geoffreyfishing at gmail
Created get_export_generator.
103
    :param fileobj: Optional file object to use
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
104
    """
105
    global _exporters, _exporter_extensions
106
5952.1.6 by geoffreyfishing at gmail
Created get_export_generator.
107
    if format is None and dest is not None:
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
108
        for ext in _exporter_extensions:
109
            if dest.endswith(ext):
110
                format = _exporter_extensions[ext]
111
                break
112
113
    # Most of the exporters will just have to call
114
    # this function anyway, so why not do it for them
115
    if root is None:
116
        root = get_root_name(dest)
117
1963.2.1 by Robey Pointer
remove usage of has_key()
118
    if format not in _exporters:
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
119
        raise errors.NoSuchExportFormat(format)
5718.5.1 by Jelmer Vernooij
per_file_timestamp -> force_mtime.
120
121
    if not per_file_timestamps:
122
        force_mtime = time.time()
123
    else:
124
        force_mtime = None
125
5718.5.4 by Jelmer Vernooij
fix timestamp in tgz files.
126
    trace.mutter('export version %r', tree)
127
6006.3.6 by Martin Pool
Deprecate export(filtered=True)
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)
6006.3.7 by Martin Pool
Remove duplicated content-filtering code from exporters
134
        # We don't want things re-filtered by the specific exporter.
135
        filtered = False
136
137
    tree.lock_read()
5952.1.16 by geoffreyfishing at gmail
Moved unlock function into finally block.
138
    try:
6006.3.6 by Martin Pool
Deprecate export(filtered=True)
139
        for _ in _exporters[format](
6006.3.7 by Martin Pool
Remove duplicated content-filtering code from exporters
140
            tree, dest, root, subdir,
6006.3.6 by Martin Pool
Deprecate export(filtered=True)
141
            force_mtime=force_mtime, fileobj=fileobj):
5952.1.16 by geoffreyfishing at gmail
Moved unlock function into finally block.
142
            yield
5967.6.1 by Martin Pool
pep8 cleanup
143
    finally:
5952.1.16 by geoffreyfishing at gmail
Moved unlock function into finally block.
144
        tree.unlock()
5952.1.15 by geoffreyfishing at gmail
Major code cleanup.
145
146
5967.6.1 by Martin Pool
pep8 cleanup
147
def export(tree, dest, format=None, root=None, subdir=None, filtered=False,
5952.1.18 by geoffreyfishing at gmail
Fixed line ending problems.
148
           per_file_timestamps=False, fileobj=None):
5952.1.6 by geoffreyfishing at gmail
Created get_export_generator.
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
6006.3.6 by Martin Pool
Deprecate export(filtered=True)
166
        files exported.  Deprecated in favor of passing an ContentFilterTree.
5967.6.1 by Martin Pool
pep8 cleanup
167
    :param per_file_timestamps: Whether to use the timestamp stored in the
168
        tree rather than now(). This will do a revision lookup
5952.1.6 by geoffreyfishing at gmail
Created get_export_generator.
169
        for every file so will be significantly slower.
170
    :param fileobj: Optional file object to use
171
    """
5967.6.1 by Martin Pool
pep8 cleanup
172
    for _ in get_export_generator(tree, dest, format, root, subdir, filtered,
5952.1.18 by geoffreyfishing at gmail
Fixed line ending problems.
173
                                  per_file_timestamps, fileobj):
5952.1.6 by geoffreyfishing at gmail
Created get_export_generator.
174
        pass
175
5967.6.1 by Martin Pool
pep8 cleanup
176
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
177
def get_root_name(dest):
178
    """Get just the root name for an export.
179
180
    """
181
    global _exporter_extensions
5718.5.18 by Jelmer Vernooij
Don't export to '-', but rather to ''.
182
    if dest == '-':
183
        # Exporting to -/foo doesn't make sense so use relative paths.
184
        return ''
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
185
    dest = os.path.basename(dest)
186
    for ext in _exporter_extensions:
187
        if dest.endswith(ext):
188
            return dest[:-len(ext)]
1185.31.13 by John Arbash Meinel
Updated the test to also test zip exports. Fixed some small bugs exposed by test suite.
189
    return dest
1185.31.12 by John Arbash Meinel
Refactored the export code to make it easier to add new export formats.
190
191
5718.5.8 by Jelmer Vernooij
add skip_special option.
192
def _export_iter_entries(tree, subdir, skip_special=True):
3613.2.2 by Robert Collins
Refactor exporters to remove obvious duplication to a helper function.
193
    """Iter the entries for tree suitable for exporting.
194
195
    :param tree: A tree object.
4988.10.2 by michal
bzr export won't fail on symlink exporting
196
    :param subdir: None or the path of an entry to start exporting from.
5718.5.8 by Jelmer Vernooij
add skip_special option.
197
    :param skip_special: Whether to skip .bzr files.
3613.2.2 by Robert Collins
Refactor exporters to remove obvious duplication to a helper function.
198
    """
5809.3.1 by Aaron Bentley
Switch to iter_entries_by_dir.
199
    if subdir == '':
200
        subdir = None
201
    if subdir is not None:
202
        subdir = subdir.rstrip('/')
203
    entries = tree.iter_entries_by_dir()
5967.6.1 by Martin Pool
pep8 cleanup
204
    entries.next()  # skip root
5809.3.1 by Aaron Bentley
Switch to iter_entries_by_dir.
205
    for path, entry in entries:
3613.2.2 by Robert Collins
Refactor exporters to remove obvious duplication to a helper function.
206
        # The .bzr* namespace is reserved for "magic" files like
207
        # .bzrignore and .bzrrules - do not export these
5809.3.1 by Aaron Bentley
Switch to iter_entries_by_dir.
208
        if skip_special and path.startswith(".bzr"):
3613.2.2 by Robert Collins
Refactor exporters to remove obvious duplication to a helper function.
209
            continue
5809.3.1 by Aaron Bentley
Switch to iter_entries_by_dir.
210
        if path == subdir:
211
            if entry.kind == 'directory':
212
                continue
213
            final_path = entry.name
214
        elif subdir is not None:
215
            if path.startswith(subdir + '/'):
216
                final_path = path[len(subdir) + 1:]
217
            else:
4010.2.1 by James Westby
Handle files that are not present in the tree when exporting (#174539)
218
                continue
219
        else:
5809.3.1 by Aaron Bentley
Switch to iter_entries_by_dir.
220
            final_path = path
221
        if not tree.has_filename(path):
222
            continue
5967.6.1 by Martin Pool
pep8 cleanup
223
5809.3.1 by Aaron Bentley
Switch to iter_entries_by_dir.
224
        yield final_path, entry
3613.2.2 by Robert Collins
Refactor exporters to remove obvious duplication to a helper function.
225
226
5952.2.1 by Vincent Ladeuil
PEP8 tweaks, lines too long, spaces at end of lines.
227
register_lazy_exporter(None, [], 'bzrlib.export.dir_exporter',
228
                       'dir_exporter_generator')
229
register_lazy_exporter('dir', [], 'bzrlib.export.dir_exporter',
230
                       'dir_exporter_generator')
231
register_lazy_exporter('tar', ['.tar'], 'bzrlib.export.tar_exporter',
232
                       'plain_tar_exporter_generator')
5967.6.1 by Martin Pool
pep8 cleanup
233
register_lazy_exporter('tgz', ['.tar.gz', '.tgz'],
234
                       'bzrlib.export.tar_exporter',
5952.2.1 by Vincent Ladeuil
PEP8 tweaks, lines too long, spaces at end of lines.
235
                       'tgz_exporter_generator')
236
register_lazy_exporter('tbz2', ['.tar.bz2', '.tbz2'],
237
                       'bzrlib.export.tar_exporter', 'tbz_exporter_generator')
238
register_lazy_exporter('tlzma', ['.tar.lzma'], 'bzrlib.export.tar_exporter',
239
                       'tar_lzma_exporter_generator')
240
register_lazy_exporter('txz', ['.tar.xz'], 'bzrlib.export.tar_exporter',
5957.3.3 by Vincent Ladeuil
Fix typo.
241
                       'tar_xz_exporter_generator')
5952.2.1 by Vincent Ladeuil
PEP8 tweaks, lines too long, spaces at end of lines.
242
register_lazy_exporter('zip', ['.zip'], 'bzrlib.export.zip_exporter',
243
                       'zip_exporter_generator')