forked from nodejs/node
-
Notifications
You must be signed in to change notification settings - Fork 2
/
nodedownload.py
143 lines (125 loc) · 4.68 KB
/
nodedownload.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/usr/bin/env python
# Moved some utilities here from ../../configure
from __future__ import print_function
import hashlib
import sys
import zipfile
import tarfile
import contextlib
try:
from urllib.request import FancyURLopener, URLopener
except ImportError:
from urllib import FancyURLopener, URLopener
def formatSize(amt):
"""Format a size as a string in MB"""
return "%.1f" % (amt / 1024000.)
def spin(c):
"""print out an ASCII 'spinner' based on the value of counter 'c'"""
spin = ".:|'"
return (spin[c % len(spin)])
class ConfigOpener(FancyURLopener):
"""fancy opener used by retrievefile. Set a UA"""
# append to existing version (UA)
version = '%s node.js/configure' % URLopener.version
def reporthook(count, size, total):
"""internal hook used by retrievefile"""
sys.stdout.write(' Fetch: %c %sMB total, %sMB downloaded \r' %
(spin(count),
formatSize(total),
formatSize(count*size)))
def retrievefile(url, targetfile):
"""fetch file 'url' as 'targetfile'. Return targetfile or throw."""
try:
sys.stdout.write(' <%s>\nConnecting...\r' % url)
sys.stdout.flush()
ConfigOpener().retrieve(url, targetfile, reporthook=reporthook)
print('') # clear the line
return targetfile
except IOError as err:
print(' ** IOError %s\n' % err)
return None
except:
print(' ** Error occurred while downloading\n <%s>' % url)
raise
def findHash(dict):
"""Find an available hash type."""
# choose from one of these
availAlgos = hashlib.algorithms_guaranteed
for hashAlgo in availAlgos:
if hashAlgo in dict:
return (dict[hashAlgo], hashAlgo, availAlgos)
# error
return (None, None, availAlgos)
def checkHash(targetfile, hashAlgo):
"""Check a file using hashAlgo. Return the hex digest."""
digest = hashlib.new(hashAlgo)
with open(targetfile, 'rb') as f:
chunk = f.read(1024)
while len(chunk) > 0:
digest.update(chunk)
chunk = f.read(1024)
return digest.hexdigest()
def unpack(packedfile, parent_path):
"""Unpacks packedfile into parent_path. Assumes .zip. Returns parent_path"""
if zipfile.is_zipfile(packedfile):
with contextlib.closing(zipfile.ZipFile(packedfile, 'r')) as icuzip:
print(' Extracting zipfile: %s' % packedfile)
icuzip.extractall(parent_path)
return parent_path
elif tarfile.is_tarfile(packedfile):
with contextlib.closing(tarfile.TarFile.open(packedfile, 'r')) as icuzip:
print(' Extracting tarfile: %s' % packedfile)
icuzip.extractall(parent_path)
return parent_path
else:
packedsuffix = packedfile.lower().split('.')[-1] # .zip, .tgz etc
raise Exception('Error: Don\'t know how to unpack %s with extension %s' % (packedfile, packedsuffix))
# List of possible "--download=" types.
download_types = set(['icu'])
# Default options for --download.
download_default = "none"
def help():
"""This function calculates the '--help' text for '--download'."""
return """Select which packages may be auto-downloaded.
valid values are: none, all, %s. (default is "%s").""" % (", ".join(download_types), download_default)
def set2dict(keys, value=None):
"""Convert some keys (iterable) to a dict."""
return dict((key, value) for (key) in keys)
def parse(opt):
"""This function parses the options to --download and returns a set such as { icu: true }, etc. """
if not opt:
opt = download_default
theOpts = set(opt.split(','))
if 'all' in theOpts:
# all on
return set2dict(download_types, True)
elif 'none' in theOpts:
# all off
return set2dict(download_types, False)
# OK. Now, process each of the opts.
theRet = set2dict(download_types, False)
for anOpt in opt.split(','):
if not anOpt or anOpt == "":
# ignore stray commas, etc.
continue
elif anOpt == 'all':
# all on
theRet = dict((key, True) for (key) in download_types)
else:
# turn this one on
if anOpt in download_types:
theRet[anOpt] = True
else:
# future proof: ignore unknown types
print('Warning: ignoring unknown --download= type "%s"' % anOpt)
# all done
return theRet
def candownload(auto_downloads, package):
if not (package in auto_downloads.keys()):
raise Exception('Internal error: "%s" is not in the --downloads list. Check nodedownload.py' % package)
if auto_downloads[package]:
return True
else:
print("""Warning: Not downloading package "%s". You could pass "--download=all"
(Windows: "download-all") to try auto-downloading it.""" % package)
return False