~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/export/tar_exporter.py

  • Committer: Vincent Ladeuil
  • Date: 2011-06-07 07:23:36 UTC
  • mfrom: (5952.1.25 tarball-generator)
  • mto: This revision was merged to the branch mainline in revision 5961.
  • Revision ID: v.ladeuil+lp@free.fr-20110607072336-us9gklyqstjyq4mt
Exporting may now be done with a generator

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 a Tree to a non-versioned directory.
18
 
"""
 
17
"""Export a Tree to a non-versioned directory."""
19
18
 
20
19
import os
21
20
import StringIO
32
31
    filtered_output_bytes,
33
32
    )
34
33
 
35
 
 
36
 
def export_tarball(tree, ball, root, subdir=None, filtered=False,
 
34
def prepare_tarball_item(tree, root, final_path, entry, filtered=False,
 
35
                         force_mtime=None):
 
36
    """Prepare a tarball item for exporting
 
37
        
 
38
    :param tree: Tree to export
 
39
 
 
40
    :param final_path: Final path to place item
 
41
 
 
42
    :param entry: Entry to export
 
43
 
 
44
    :param filtered: Whether to apply filters
 
45
 
 
46
    :param force_mtime: Option mtime to force, instead of using tree timestamps.
 
47
    
 
48
    Returns a (tarinfo, fileobj) tuple
 
49
    """
 
50
    filename = osutils.pathjoin(root, final_path).encode('utf8')
 
51
    item = tarfile.TarInfo(filename)
 
52
    if force_mtime is not None:
 
53
        item.mtime = force_mtime
 
54
    else:
 
55
        item.mtime = tree.get_file_mtime(entry.file_id, final_path)
 
56
    if entry.kind == "file":
 
57
        item.type = tarfile.REGTYPE
 
58
        if tree.is_executable(entry.file_id):
 
59
            item.mode = 0755
 
60
        else:
 
61
            item.mode = 0644
 
62
        if filtered:
 
63
            chunks = tree.get_file_lines(entry.file_id)
 
64
            filters = tree._content_filter_stack(final_path)
 
65
            context = ContentFilterContext(final_path, tree, entry)
 
66
            contents = filtered_output_bytes(chunks, filters, context)
 
67
            content = ''.join(contents)
 
68
            item.size = len(content)
 
69
            fileobj = StringIO.StringIO(content)
 
70
        else:
 
71
            item.size = tree.get_file_size(entry.file_id)
 
72
            fileobj = tree.get_file(entry.file_id)
 
73
    elif entry.kind == "directory":
 
74
        item.type = tarfile.DIRTYPE
 
75
        item.name += '/'
 
76
        item.size = 0
 
77
        item.mode = 0755
 
78
        fileobj = None
 
79
    elif entry.kind == "symlink":
 
80
        item.type = tarfile.SYMTYPE
 
81
        item.size = 0
 
82
        item.mode = 0755
 
83
        item.linkname = tree.get_symlink_target(entry.file_id)
 
84
        fileobj = None
 
85
    else:
 
86
        raise errors.BzrError("don't know how to export {%s} of kind %r" 
 
87
                              % (entry.file_id, entry.kind))
 
88
    
 
89
    return (item, fileobj)
 
90
 
 
91
def export_tarball_generator(tree, ball, root, subdir=None, filtered=False,
37
92
                   force_mtime=None):
38
 
    """Export tree contents to a tarball.
 
93
    """Export tree contents to a tarball. This is a generator.
39
94
 
40
95
    :param tree: Tree to export
 
96
 
41
97
    :param ball: Tarball to export to
 
98
 
42
99
    :param filtered: Whether to apply filters
 
100
 
43
101
    :param subdir: Sub directory to export
44
 
    :param force_mtime: Option mtime to force, instead of using
45
 
        tree timestamps.
 
102
 
 
103
    :param force_mtime: Option mtime to force, instead of using tree
 
104
        timestamps.
46
105
    """
47
 
    for dp, ie in _export_iter_entries(tree, subdir):
48
 
        filename = osutils.pathjoin(root, dp).encode('utf8')
49
 
        item = tarfile.TarInfo(filename)
50
 
        if force_mtime is not None:
51
 
            item.mtime = force_mtime
52
 
        else:
53
 
            item.mtime = tree.get_file_mtime(ie.file_id, dp)
54
 
        if ie.kind == "file":
55
 
            item.type = tarfile.REGTYPE
56
 
            if tree.is_executable(ie.file_id):
57
 
                item.mode = 0755
58
 
            else:
59
 
                item.mode = 0644
60
 
            if filtered:
61
 
                chunks = tree.get_file_lines(ie.file_id)
62
 
                filters = tree._content_filter_stack(dp)
63
 
                context = ContentFilterContext(dp, tree, ie)
64
 
                contents = filtered_output_bytes(chunks, filters, context)
65
 
                content = ''.join(contents)
66
 
                item.size = len(content)
67
 
                fileobj = StringIO.StringIO(content)
68
 
            else:
69
 
                item.size = tree.get_file_size(ie.file_id)
70
 
                fileobj = tree.get_file(ie.file_id)
71
 
        elif ie.kind == "directory":
72
 
            item.type = tarfile.DIRTYPE
73
 
            item.name += '/'
74
 
            item.size = 0
75
 
            item.mode = 0755
76
 
            fileobj = None
77
 
        elif ie.kind == "symlink":
78
 
            item.type = tarfile.SYMTYPE
79
 
            item.size = 0
80
 
            item.mode = 0755
81
 
            item.linkname = tree.get_symlink_target(ie.file_id)
82
 
            fileobj = None
83
 
        else:
84
 
            raise errors.BzrError("don't know how to export {%s} of kind %r" %
85
 
                           (ie.file_id, ie.kind))
 
106
    for final_path, entry in _export_iter_entries(tree, subdir):
 
107
 
 
108
        (item, fileobj) = prepare_tarball_item(tree, root, final_path,
 
109
                                               entry, filtered, force_mtime)
86
110
        ball.addfile(item, fileobj)
87
111
 
88
 
 
89
 
def tgz_exporter(tree, dest, root, subdir, filtered=False, force_mtime=None):
 
112
        yield
 
113
 
 
114
 
 
115
def export_tarball(tree, ball, root, subdir=None, filtered=False,
 
116
                   force_mtime=None):
 
117
 
 
118
    for _ in export_tarball_generator(tree, ball, root, subdir, filtered,
 
119
                                      force_mtime):
 
120
        pass
 
121
 
 
122
def tgz_exporter_generator(tree, dest, root, subdir, filtered=False,
 
123
                           force_mtime=None, fileobj=None):
90
124
    """Export this tree to a new tar file.
91
125
 
92
126
    `dest` will be created holding the contents of this tree; if it
106
140
        root_mtime = None
107
141
 
108
142
    is_stdout = False
109
 
    if dest == '-':
 
143
    if fileobj is not None:
 
144
        stream = fileobj
 
145
    elif dest == '-':
110
146
        basename = None
111
147
        stream = sys.stdout
112
148
        is_stdout = True
117
153
        # dest. (bug 102234)
118
154
        basename = os.path.basename(dest)
119
155
    try:
120
 
        zipstream = gzip.GzipFile(basename, 'w', fileobj=stream, mtime=root_mtime)
 
156
        zipstream = gzip.GzipFile(basename, 'w', fileobj=stream,
 
157
                                  mtime=root_mtime)
121
158
    except TypeError:
122
159
        # Python < 2.7 doesn't support the mtime argument
123
160
        zipstream = gzip.GzipFile(basename, 'w', fileobj=stream)
124
161
    ball = tarfile.open(None, 'w|', fileobj=zipstream)
125
 
    export_tarball(tree, ball, root, subdir, filtered=filtered,
126
 
                   force_mtime=force_mtime)
127
 
    ball.close()
 
162
 
 
163
    for _ in export_tarball_generator(tree, ball, root, subdir, filtered,
 
164
                                      force_mtime):
 
165
 
 
166
        yield
 
167
 
128
168
    zipstream.close()
129
169
    if not is_stdout:
130
170
        stream.close()
131
171
 
132
172
 
133
 
def tbz_exporter(tree, dest, root, subdir, filtered=False, force_mtime=None):
 
173
def tgz_exporter(tree, dest, root, subdir, filtered=False, force_mtime=None,
 
174
                 fileobj=None):
 
175
 
 
176
    for _ in tgz_exporter_generator(tree, dest, root, subdir, filtered,
 
177
                                    force_mtime, fileobj):
 
178
        pass
 
179
 
 
180
 
 
181
def tbz_exporter_generator(tree, dest, root, subdir, filtered=False,
 
182
                           force_mtime=None, fileobj=None):
134
183
    """Export this tree to a new tar file.
135
184
 
136
185
    `dest` will be created holding the contents of this tree; if it
137
186
    already exists, it will be clobbered, like with "tar -c".
138
187
    """
139
 
    if dest == '-':
 
188
    if fileobj is not None:
 
189
        ball = tarfile.open(None, 'w|bz2', fileobj)
 
190
    elif dest == '-':
140
191
        ball = tarfile.open(None, 'w|bz2', sys.stdout)
141
192
    else:
142
193
        # tarfile.open goes on to do 'os.getcwd() + dest' for opening
145
196
        # upstream python bug http://bugs.python.org/issue8396
146
197
        # (fixed in Python 2.6.5 and 2.7b1)
147
198
        ball = tarfile.open(dest.encode(osutils._fs_enc), 'w:bz2')
148
 
    export_tarball(tree, ball, root, subdir, filtered=filtered,
149
 
                   force_mtime=force_mtime)
150
 
    ball.close()
151
 
 
 
199
 
 
200
    for _ in export_tarball_generator(tree, ball, root, subdir, filtered,
 
201
                                      force_mtime):
 
202
        yield
 
203
 
 
204
    ball.close()
 
205
 
 
206
 
 
207
def tbz_exporter(tree, dest, root, subdir, filtered=False, force_mtime=None,
 
208
                 fileobj=None):
 
209
 
 
210
    for _ in tbz_exporter_generator(tree, dest, root, subdir, filtered,
 
211
                                    force_mtime, fileobj):
 
212
        pass
 
213
 
 
214
 
 
215
def plain_tar_exporter_generator(tree, dest, root, subdir, compression=None,
 
216
                                 filtered=False, force_mtime=None,
 
217
                                 fileobj=None):
 
218
    """Export this tree to a new tar file.
 
219
 
 
220
    `dest` will be created holding the contents of this tree; if it
 
221
    already exists, it will be clobbered, like with "tar -c".
 
222
    """
 
223
    if fileobj is not None:
 
224
        stream = fileobj
 
225
    elif dest == '-':
 
226
        stream = sys.stdout
 
227
    else:
 
228
        stream = open(dest, 'wb')
 
229
    ball = tarfile.open(None, 'w|', stream)
 
230
 
 
231
    for _ in export_tarball_generator(tree, ball, root, subdir, filtered,
 
232
                                      force_mtime):
 
233
 
 
234
        yield
 
235
 
 
236
    ball.close()
152
237
 
153
238
def plain_tar_exporter(tree, dest, root, subdir, compression=None,
154
 
                       filtered=False, force_mtime=None):
155
 
    """Export this tree to a new tar file.
156
 
 
157
 
    `dest` will be created holding the contents of this tree; if it
158
 
    already exists, it will be clobbered, like with "tar -c".
159
 
    """
160
 
    if dest == '-':
161
 
        stream = sys.stdout
162
 
    else:
163
 
        stream = open(dest, 'wb')
164
 
    ball = tarfile.open(None, 'w|', stream)
165
 
    export_tarball(tree, ball, root, subdir, filtered=filtered,
166
 
                   force_mtime=force_mtime)
167
 
    ball.close()
168
 
 
169
 
 
170
 
def tar_xz_exporter(tree, dest, root, subdir, filtered=False,
171
 
                    force_mtime=None):
172
 
    return tar_lzma_exporter(tree, dest, root, subdir, filtered=filtered,
173
 
        force_mtime=force_mtime, compression_format="xz")
174
 
 
175
 
 
176
 
def tar_lzma_exporter(tree, dest, root, subdir, filtered=False, force_mtime=None, compression_format="alone"):
 
239
                       filtered=False, force_mtime=None, fileobj=None):
 
240
 
 
241
    for _ in plain_tar_exporter_generator(
 
242
        tree, dest, root, subdir, compression, filtered, force_mtime, fileobj):
 
243
        pass
 
244
 
 
245
 
 
246
def tar_xz_exporter_generator(tree, dest, root, subdir, filtered=False,
 
247
                              force_mtime=None, fileobj=None):
 
248
 
 
249
    return tar_lzma_exporter_generator(tree, dest, root, subdir, filtered,
 
250
                                       force_mtime, fileobj, "xz")
 
251
 
 
252
 
 
253
def tar_xz_exporter(tree, dest, root, subdir, filtered=False, force_mtime=None,
 
254
                     fileobj=None):
 
255
    for _ in tar_xz_exporter_generator(tree, dest, root, subdir, filtered,
 
256
                                       force_mtime, fileobj):
 
257
        pass
 
258
 
 
259
 
 
260
def tar_lzma_exporter_generator(tree, dest, root, subdir, filtered=False,
 
261
                      force_mtime=None, fileobj=None,
 
262
                                compression_format="alone"):
177
263
    """Export this tree to a new .tar.lzma file.
178
264
 
179
265
    `dest` will be created holding the contents of this tree; if it
182
268
    if dest == '-':
183
269
        raise errors.BzrError("Writing to stdout not supported for .tar.lzma")
184
270
 
 
271
    if fileobj is not None:
 
272
        raise errors.BzrError(
 
273
            "Writing to fileobject not supported for .tar.lzma")
185
274
    try:
186
275
        import lzma
187
276
    except ImportError, e:
190
279
    stream = lzma.LZMAFile(dest.encode(osutils._fs_enc), 'w',
191
280
            options={"format": compression_format})
192
281
    ball = tarfile.open(None, 'w:', fileobj=stream)
193
 
    export_tarball(tree, ball, root, subdir, filtered=filtered,
194
 
                   force_mtime=force_mtime)
 
282
 
 
283
    for _ in export_tarball_generator(
 
284
        tree, ball, root, subdir, filtered=filtered, force_mtime=force_mtime):
 
285
        yield
 
286
 
195
287
    ball.close()
196
288
 
 
289
 
 
290
def tar_lzma_exporter(tree, dest, root, subdir, filtered=False,
 
291
                      force_mtime=None, fileobj=None,
 
292
                      compression_format="alone"):
 
293
    for _ in tar_lzma_exporter_generator(tree, dest, root, subdir, filtered,
 
294
                                         force_mtime, fileobj,
 
295
                                         compression_format):
 
296
        pass