Path: blob/develop/build/sage_bootstrap/uncompress/action.py
4055 views
"""1"""23#*****************************************************************************4# Copyright (C) 2016 Volker Braun <[email protected]>5#6# This program is free software: you can redistribute it and/or modify7# it under the terms of the GNU General Public License as published by8# the Free Software Foundation, either version 2 of the License, or9# (at your option) any later version.10# http://www.gnu.org/licenses/11#*****************************************************************************1213from __future__ import print_function1415import os1617from sage_bootstrap.uncompress.tar_file import SageTarFile, SageTarXZFile18from sage_bootstrap.uncompress.zip_file import SageZipFile19from sage_bootstrap.util import retry2021ARCHIVE_TYPES = [SageTarFile, SageZipFile, SageTarXZFile]222324def open_archive(filename):25"""26Automatically detect archive type27"""28for cls in ARCHIVE_TYPES:29if cls.can_read(filename):30break31else:32raise ValueError3334# For now ZipFile and TarFile both have default open modes that are35# acceptable36return cls(filename)373839def unpack_archive(archive, dirname=None):40"""41Unpack archive42"""43top_level = None4445if dirname:46top_levels = set()47for member in archive.names:48# Zip and tar files all use forward slashes as separators49# internally50top_levels.add(member.split('/', 1)[0])5152if len(top_levels) == 1:53top_level = top_levels.pop()54else:55os.makedirs(dirname)5657prev_cwd = os.getcwd()5859if dirname and not top_level:60# We want to extract content into dirname, but there is not61# a single top-level directory for the tarball, so we cd into62# the extraction target first63os.chdir(dirname)6465try:66archive.extractall(members=archive.names)67if dirname and top_level:68# On Windows os.rename can fail unexpectedly with a permission69# error if a virus scanner or other background process is70# inspecting the newly extracted files71rename = lambda: os.rename(top_level, dirname)72retry(rename, OSError, tries=len(archive.names))7374# Apply typical umask to the top-level directory in case it wasn't75# already; see https://github.com/sagemath/sage/issues/2456776# and later https://github.com/sagemath/sage/issues/2859677os.chmod(dirname, os.stat(dirname).st_mode & ~0o022)78finally:79os.chdir(prev_cwd)808182