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
17
"""Export trees to tarballs, non-controlled directories, zipfiles, etc.
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
"""Export functionality, which can take a Tree and create a different representation.
19
Such as non-controlled directories, tarfiles, zipfiles, etc.
20
from __future__ import absolute_import
22
from bzrlib.trace import mutter
24
import bzrlib.errors as errors
32
26
# Maps format name => export function
34
28
# Maps filename extensions => export format name
35
29
_exporter_extensions = {}
38
31
def register_exporter(format, extensions, func, override=False):
39
32
"""Register an exporter.
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)
63
56
When requesting a specific type of export, load the respective path.
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,
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)
73
def get_export_generator(tree, dest=None, format=None, root=None, subdir=None,
74
filtered=False, per_file_timestamps=False,
76
"""Returns a generator that exports the given tree.
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.
81
68
:param tree: A Tree (such as RevisionTree) to export
83
:param dest: The destination where the files, etc should be put
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
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.
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
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.
97
:param filtered: If True, content filtering is applied to the exported
98
files. Deprecated in favour of passing a ContentFilterTree
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.
105
:param fileobj: Optional file object to use
107
83
global _exporters, _exporter_extensions
109
if format is None and dest is not None:
110
86
for ext in _exporter_extensions:
111
87
if dest.endswith(ext):
112
88
format = _exporter_extensions[ext]
120
96
if format not in _exporters:
121
97
raise errors.NoSuchExportFormat(format)
123
if not per_file_timestamps:
124
force_mtime = time.time()
128
trace.mutter('export version %r', tree)
131
from bzrlib.filter_tree import ContentFilterTree
133
"passing filtered=True to export is deprecated in bzr 2.4",
135
tree = ContentFilterTree(tree, tree._content_filter_stack)
136
# We don't want things re-filtered by the specific exporter.
141
for _ in _exporters[format](
142
tree, dest, root, subdir,
143
force_mtime=force_mtime, fileobj=fileobj):
100
return _exporters[format](tree, dest, root, subdir)
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.
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
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
174
for _ in get_export_generator(tree, dest, format, root, subdir, filtered,
175
per_file_timestamps, fileobj):
179
105
def get_root_name(dest):
180
106
"""Get just the root name for an export.
108
>>> get_root_name('../mytest.tar')
110
>>> get_root_name('mytar.tar')
112
>>> get_root_name('mytar.tar.bz2')
114
>>> get_root_name('tar.tar.tar.tgz')
116
>>> get_root_name('bzr-0.0.5.tar.gz')
118
>>> get_root_name('bzr-0.0.5.zip')
120
>>> get_root_name('bzr-0.0.5')
122
>>> get_root_name('a/long/path/mytar.tgz')
124
>>> get_root_name('../parent/../dir/other.tbz2')
183
127
global _exporter_extensions
185
# Exporting to -/foo doesn't make sense so use relative paths.
187
128
dest = os.path.basename(dest)
188
129
for ext in _exporter_extensions:
189
130
if dest.endswith(ext):
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.
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.
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:
145
subdir_id = inv.path2id(subdir)
146
entries = inv.iter_entries(subdir_id)
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"):
215
if entry.kind == 'directory':
217
final_path = entry.name
218
elif subdir is not None:
219
if path.startswith(subdir + '/'):
220
final_path = path[len(subdir) + 1:]
225
if not tree.has_filename(path):
228
yield final_path, path, entry
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"):
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')