• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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