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