~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/export/__init__.py

  • Committer: John Arbash Meinel
  • Author(s): Mark Hammond
  • Date: 2008-09-09 17:02:21 UTC
  • mto: This revision was merged to the branch mainline in revision 3697.
  • Revision ID: john@arbash-meinel.com-20080909170221-svim3jw2mrz0amp3
An updated transparent icon for bzr.

Show diffs side-by-side

added added

removed removed

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