Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sage
Path: blob/develop/build/sage_bootstrap/uncompress/action.py
4055 views
1
"""
2
"""
3
4
#*****************************************************************************
5
# Copyright (C) 2016 Volker Braun <[email protected]>
6
#
7
# This program is free software: you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation, either version 2 of the License, or
10
# (at your option) any later version.
11
# http://www.gnu.org/licenses/
12
#*****************************************************************************
13
14
from __future__ import print_function
15
16
import os
17
18
from sage_bootstrap.uncompress.tar_file import SageTarFile, SageTarXZFile
19
from sage_bootstrap.uncompress.zip_file import SageZipFile
20
from sage_bootstrap.util import retry
21
22
ARCHIVE_TYPES = [SageTarFile, SageZipFile, SageTarXZFile]
23
24
25
def open_archive(filename):
26
"""
27
Automatically detect archive type
28
"""
29
for cls in ARCHIVE_TYPES:
30
if cls.can_read(filename):
31
break
32
else:
33
raise ValueError
34
35
# For now ZipFile and TarFile both have default open modes that are
36
# acceptable
37
return cls(filename)
38
39
40
def unpack_archive(archive, dirname=None):
41
"""
42
Unpack archive
43
"""
44
top_level = None
45
46
if dirname:
47
top_levels = set()
48
for member in archive.names:
49
# Zip and tar files all use forward slashes as separators
50
# internally
51
top_levels.add(member.split('/', 1)[0])
52
53
if len(top_levels) == 1:
54
top_level = top_levels.pop()
55
else:
56
os.makedirs(dirname)
57
58
prev_cwd = os.getcwd()
59
60
if dirname and not top_level:
61
# We want to extract content into dirname, but there is not
62
# a single top-level directory for the tarball, so we cd into
63
# the extraction target first
64
os.chdir(dirname)
65
66
try:
67
archive.extractall(members=archive.names)
68
if dirname and top_level:
69
# On Windows os.rename can fail unexpectedly with a permission
70
# error if a virus scanner or other background process is
71
# inspecting the newly extracted files
72
rename = lambda: os.rename(top_level, dirname)
73
retry(rename, OSError, tries=len(archive.names))
74
75
# Apply typical umask to the top-level directory in case it wasn't
76
# already; see https://github.com/sagemath/sage/issues/24567
77
# and later https://github.com/sagemath/sage/issues/28596
78
os.chmod(dirname, os.stat(dirname).st_mode & ~0o022)
79
finally:
80
os.chdir(prev_cwd)
81
82