~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to upstream_import.py

  • Committer: Aaron Bentley
  • Date: 2009-07-13 19:14:10 UTC
  • Revision ID: aaron@aaronbentley.com-20090713191410-dhqsqf3kuz5x2oyd
Tags: release-1.17.0
Update NEWS for release 1.17.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
"""Import upstream source into a branch"""
2
2
 
 
3
from bz2 import BZ2File
3
4
import errno
4
5
import os
5
 
import re
6
6
from StringIO import StringIO
7
7
import stat
8
8
import tarfile
17
17
from bzrlib.transform import TreeTransform, resolve_conflicts, cook_conflicts
18
18
from bzrlib.workingtree import WorkingTree
19
19
from bzrlib.plugins.bzrtools.bzrtools import open_from_url
20
 
from bzrlib.plugins.bzrtools import errors
21
20
 
22
21
class ZipFileWrapper(object):
23
22
 
164
163
            yield member.name
165
164
 
166
165
 
167
 
def should_ignore(relative_path):
168
 
    return top_path(relative_path) == '.bzr'
169
 
 
170
 
 
171
166
def import_tar(tree, tar_input):
172
167
    """Replace the contents of a working directory with tarfile contents.
173
168
    The tarfile may be a gzipped stream.  File ids will be updated.
183
178
    dir_file = DirWrapper(dir_input)
184
179
    import_archive(tree, dir_file)
185
180
 
186
 
 
187
181
def import_archive(tree, archive_file):
 
182
    prefix = common_directory(names_of_files(archive_file))
188
183
    tt = TreeTransform(tree)
189
 
    try:
190
 
        import_archive_to_transform(tree, archive_file, tt)
191
 
        tt.apply()
192
 
    finally:
193
 
        tt.finalize()
194
 
 
195
 
 
196
 
def import_archive_to_transform(tree, archive_file, tt):
197
 
    prefix = common_directory(names_of_files(archive_file))
 
184
 
198
185
    removed = set()
199
 
    for path, entry in tree.iter_entries_by_dir():
 
186
    for path, entry in tree.inventory.iter_entries():
200
187
        if entry.parent_id is None:
201
188
            continue
202
189
        trans_id = tt.trans_id_tree_path(path)
210
197
        if member.type == 'g':
211
198
            # type 'g' is a header
212
199
            continue
213
 
        # Inverse functionality in bzr uses utf-8.  We could also
214
 
        # interpret relative to fs encoding, which would match native
215
 
        # behaviour better.
216
 
        relative_path = member.name.decode('utf-8')
 
200
        relative_path = member.name
217
201
        if prefix is not None:
218
202
            relative_path = relative_path[len(prefix)+1:]
219
203
            relative_path = relative_path.rstrip('/')
220
204
        if relative_path == '':
221
205
            continue
222
 
        if should_ignore(relative_path):
223
 
            continue
224
206
        add_implied_parents(implied_parents, relative_path)
225
207
        trans_id = tt.trans_id_tree_path(relative_path)
226
208
        added.add(relative_path.rstrip('/'))
261
243
 
262
244
    for conflict in cook_conflicts(resolve_conflicts(tt), tt):
263
245
        warning(conflict)
 
246
    tt.apply()
264
247
 
265
248
 
266
249
def do_import(source, tree_directory=None):
280
263
        if tree.changes_from(tree.basis_tree()).has_changed():
281
264
            raise BzrCommandError("Working tree has uncommitted changes.")
282
265
 
283
 
        try:
284
 
            archive, external_compressor = get_archive_type(source)
285
 
        except errors.NotArchiveType:
286
 
            if file_kind(source) == 'directory':
287
 
                s = StringIO(source)
288
 
                s.seek(0)
289
 
                import_dir(tree, s)
290
 
            else:
291
 
                raise BzrCommandError('Unhandled import source')
 
266
        if (source.endswith('.tar') or source.endswith('.tar.gz') or
 
267
            source.endswith('.tar.bz2')) or source.endswith('.tgz'):
 
268
            try:
 
269
                tar_input = open_from_url(source)
 
270
                if source.endswith('.bz2'):
 
271
                    tar_input = StringIO(tar_input.read().decode('bz2'))
 
272
            except IOError, e:
 
273
                if e.errno == errno.ENOENT:
 
274
                    raise NoSuchFile(source)
 
275
            try:
 
276
                import_tar(tree, tar_input)
 
277
            finally:
 
278
                tar_input.close()
 
279
        elif source.endswith('.zip'):
 
280
            import_zip(tree, open_from_url(source))
 
281
        elif file_kind(source) == 'directory':
 
282
            s = StringIO(source)
 
283
            s.seek(0)
 
284
            import_dir(tree, s)
292
285
        else:
293
 
            if archive == 'zip':
294
 
                import_zip(tree, open_from_url(source))
295
 
            elif archive == 'tar':
296
 
                try:
297
 
                    tar_input = open_from_url(source)
298
 
                    if external_compressor == 'bz2':
299
 
                        import bz2
300
 
                        tar_input = StringIO(bz2.decompress(tar_input.read()))
301
 
                    elif external_compressor == 'lzma':
302
 
                        import lzma
303
 
                        tar_input = StringIO(lzma.decompress(tar_input.read()))
304
 
                except IOError, e:
305
 
                    if e.errno == errno.ENOENT:
306
 
                        raise NoSuchFile(source)
307
 
                try:
308
 
                    import_tar(tree, tar_input)
309
 
                finally:
310
 
                    tar_input.close()
 
286
            raise BzrCommandError('Unhandled import source')
311
287
    finally:
312
288
        tree.unlock()
313
 
 
314
 
 
315
 
def get_archive_type(path):
316
 
    """Return the type of archive and compressor indicated by path name.
317
 
 
318
 
    Only external compressors are returned, so zip files are only
319
 
    ('zip', None).  .tgz is treated as ('tar', 'gz') and '.tar.xz' is treated
320
 
    as ('tar', 'lzma').
321
 
    """
322
 
    matches = re.match(r'.*\.(zip|tgz|tar(.(gz|bz2|lzma|xz))?)$', path)
323
 
    if not matches:
324
 
        raise errors.NotArchiveType(path)
325
 
    external_compressor = None
326
 
    if matches.group(3) is not None:
327
 
        archive = 'tar'
328
 
        external_compressor = matches.group(3)
329
 
        if external_compressor == 'xz':
330
 
            external_compressor = 'lzma'
331
 
    elif matches.group(1) == 'tgz':
332
 
        return 'tar', 'gz'
333
 
    else:
334
 
        archive = matches.group(1)
335
 
    return archive, external_compressor