blob: 6dbfdcb7a22c201f875d0a251fd74d6ec1bbea50 [file] [log] [blame]
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Standalone python script to unzip an archive. Intended to be used by 'zip'
recipe module internally. Should not be used elsewhere.
"""
import json
import os
import shutil
import subprocess
import sys
import zipfile
def unzip_with_subprocess(zip_file, output, quiet):
"""Unzips an archive using 'zip' utility.
Works only on Linux and Mac, uses system 'zip' program.
Args:
zip_file: absolute path to an archive to unzip.
output: existing directory to unzip to.
quiet (bool): If True, instruct the subprocess to unzip with
minimal output.
Returns:
Exit code (0 on success).
"""
args = ['unzip']
if quiet:
args += ['-q']
args += [zip_file]
return subprocess.call(
args=args,
cwd=output)
def unzip_with_python(zip_file, output):
"""Unzips an archive using 'zipfile' python module.
Works everywhere where python works (Windows and Posix).
Args:
zip_file: absolute path to an archive to unzip.
output: existing directory to unzip to.
Returns:
Exit code (0 on success).
"""
with zipfile.ZipFile(zip_file) as zip_file_obj:
for name in zip_file_obj.namelist():
print('Extracting %s' % name)
zip_file_obj.extract(name, output)
return 0
def main():
# See zip/api.py, def unzip(...) for format of |data|.
data = json.load(sys.stdin)
output = data['output']
zip_file = data['zip_file']
quiet = data['quiet']
# Archive path should exist and be an absolute path to a file.
assert os.path.exists(zip_file), zip_file
assert os.path.isfile(zip_file), zip_file
# Output path should be an absolute path, and should NOT exist.
assert os.path.isabs(output), output
assert not os.path.exists(output), output
print('Unzipping %s...' % zip_file)
exit_code = -1
try:
os.makedirs(output)
if sys.platform == 'win32':
# Used on Windows, since there's no builtin 'unzip' utility there.
exit_code = unzip_with_python(zip_file, output)
else:
# On mac and linux 'unzip' utility handles symlink and file modes.
exit_code = unzip_with_subprocess(zip_file, output, quiet)
finally:
# On non-zero exit code or on unexpected exception, clean up.
if exit_code:
shutil.rmtree(output, ignore_errors=True)
return exit_code
if __name__ == '__main__':
sys.exit(main())