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
22
21
class ZipFileWrapper(object):
164
163
yield member.name
167
def should_ignore(relative_path):
168
return top_path(relative_path) == '.bzr'
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)
187
181
def import_archive(tree, archive_file):
182
prefix = common_directory(names_of_files(archive_file))
188
183
tt = TreeTransform(tree)
190
import_archive_to_transform(tree, archive_file, tt)
196
def import_archive_to_transform(tree, archive_file, tt):
197
prefix = common_directory(names_of_files(archive_file))
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:
202
189
trans_id = tt.trans_id_tree_path(path)
210
197
if member.type == 'g':
211
198
# type 'g' is a header
213
# Inverse functionality in bzr uses utf-8. We could also
214
# interpret relative to fs encoding, which would match native
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 == '':
222
if should_ignore(relative_path):
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('/'))
280
263
if tree.changes_from(tree.basis_tree()).has_changed():
281
264
raise BzrCommandError("Working tree has uncommitted changes.")
284
archive, external_compressor = get_archive_type(source)
285
except errors.NotArchiveType:
286
if file_kind(source) == 'directory':
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'):
269
tar_input = open_from_url(source)
270
if source.endswith('.bz2'):
271
tar_input = StringIO(tar_input.read().decode('bz2'))
273
if e.errno == errno.ENOENT:
274
raise NoSuchFile(source)
276
import_tar(tree, tar_input)
279
elif source.endswith('.zip'):
280
import_zip(tree, open_from_url(source))
281
elif file_kind(source) == 'directory':
294
import_zip(tree, open_from_url(source))
295
elif archive == 'tar':
297
tar_input = open_from_url(source)
298
if external_compressor == 'bz2':
300
tar_input = StringIO(bz2.decompress(tar_input.read()))
301
elif external_compressor == 'lzma':
303
tar_input = StringIO(lzma.decompress(tar_input.read()))
305
if e.errno == errno.ENOENT:
306
raise NoSuchFile(source)
308
import_tar(tree, tar_input)
286
raise BzrCommandError('Unhandled import source')
315
def get_archive_type(path):
316
"""Return the type of archive and compressor indicated by path name.
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
322
matches = re.match(r'.*\.(zip|tgz|tar(.(gz|bz2|lzma|xz))?)$', path)
324
raise errors.NotArchiveType(path)
325
external_compressor = None
326
if matches.group(3) is not None:
328
external_compressor = matches.group(3)
329
if external_compressor == 'xz':
330
external_compressor = 'lzma'
331
elif matches.group(1) == 'tgz':
334
archive = matches.group(1)
335
return archive, external_compressor