11cb0ef41Sopenharmony_ci#!/usr/bin/env python
21cb0ef41Sopenharmony_ci# Moved some utilities here from ../../configure
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_cifrom __future__ import print_function
51cb0ef41Sopenharmony_ciimport hashlib
61cb0ef41Sopenharmony_ciimport sys
71cb0ef41Sopenharmony_ciimport zipfile
81cb0ef41Sopenharmony_ciimport tarfile
91cb0ef41Sopenharmony_ciimport contextlib
101cb0ef41Sopenharmony_citry:
111cb0ef41Sopenharmony_ci    from urllib.request import FancyURLopener, URLopener
121cb0ef41Sopenharmony_ciexcept ImportError:
131cb0ef41Sopenharmony_ci    from urllib import FancyURLopener, URLopener
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_cidef formatSize(amt):
161cb0ef41Sopenharmony_ci    """Format a size as a string in MB"""
171cb0ef41Sopenharmony_ci    return "%.1f" % (amt / 1024000.)
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_cidef spin(c):
201cb0ef41Sopenharmony_ci    """print out an ASCII 'spinner' based on the value of counter 'c'"""
211cb0ef41Sopenharmony_ci    spin = ".:|'"
221cb0ef41Sopenharmony_ci    return (spin[c % len(spin)])
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ciclass ConfigOpener(FancyURLopener):
251cb0ef41Sopenharmony_ci    """fancy opener used by retrievefile. Set a UA"""
261cb0ef41Sopenharmony_ci    # append to existing version (UA)
271cb0ef41Sopenharmony_ci    version = '%s node.js/configure' % URLopener.version
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_cidef reporthook(count, size, total):
301cb0ef41Sopenharmony_ci    """internal hook used by retrievefile"""
311cb0ef41Sopenharmony_ci    sys.stdout.write(' Fetch: %c %sMB total, %sMB downloaded   \r' %
321cb0ef41Sopenharmony_ci                     (spin(count),
331cb0ef41Sopenharmony_ci                      formatSize(total),
341cb0ef41Sopenharmony_ci                      formatSize(count*size)))
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_cidef retrievefile(url, targetfile):
371cb0ef41Sopenharmony_ci    """fetch file 'url' as 'targetfile'. Return targetfile or throw."""
381cb0ef41Sopenharmony_ci    try:
391cb0ef41Sopenharmony_ci        sys.stdout.write(' <%s>\nConnecting...\r' % url)
401cb0ef41Sopenharmony_ci        sys.stdout.flush()
411cb0ef41Sopenharmony_ci        ConfigOpener().retrieve(url, targetfile, reporthook=reporthook)
421cb0ef41Sopenharmony_ci        print('')  # clear the line
431cb0ef41Sopenharmony_ci        return targetfile
441cb0ef41Sopenharmony_ci    except IOError as err:
451cb0ef41Sopenharmony_ci        print(' ** IOError %s\n' % err)
461cb0ef41Sopenharmony_ci        return None
471cb0ef41Sopenharmony_ci    except:
481cb0ef41Sopenharmony_ci        print(' ** Error occurred while downloading\n <%s>' % url)
491cb0ef41Sopenharmony_ci        raise
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_cidef findHash(dict):
521cb0ef41Sopenharmony_ci    """Find an available hash type."""
531cb0ef41Sopenharmony_ci    # choose from one of these
541cb0ef41Sopenharmony_ci    availAlgos = hashlib.algorithms_guaranteed
551cb0ef41Sopenharmony_ci    for hashAlgo in availAlgos:
561cb0ef41Sopenharmony_ci      if hashAlgo in dict:
571cb0ef41Sopenharmony_ci        return (dict[hashAlgo], hashAlgo, availAlgos)
581cb0ef41Sopenharmony_ci    # error
591cb0ef41Sopenharmony_ci    return (None, None, availAlgos)
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_cidef checkHash(targetfile, hashAlgo):
621cb0ef41Sopenharmony_ci    """Check a file using hashAlgo. Return the hex digest."""
631cb0ef41Sopenharmony_ci    digest = hashlib.new(hashAlgo)
641cb0ef41Sopenharmony_ci    with open(targetfile, 'rb') as f:
651cb0ef41Sopenharmony_ci      chunk = f.read(1024)
661cb0ef41Sopenharmony_ci      while len(chunk) > 0:
671cb0ef41Sopenharmony_ci        digest.update(chunk)
681cb0ef41Sopenharmony_ci        chunk = f.read(1024)
691cb0ef41Sopenharmony_ci    return digest.hexdigest()
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_cidef unpack(packedfile, parent_path):
721cb0ef41Sopenharmony_ci    """Unpacks packedfile into parent_path. Assumes .zip. Returns parent_path"""
731cb0ef41Sopenharmony_ci    if zipfile.is_zipfile(packedfile):
741cb0ef41Sopenharmony_ci        with contextlib.closing(zipfile.ZipFile(packedfile, 'r')) as icuzip:
751cb0ef41Sopenharmony_ci            print(' Extracting zipfile: %s' % packedfile)
761cb0ef41Sopenharmony_ci            icuzip.extractall(parent_path)
771cb0ef41Sopenharmony_ci            return parent_path
781cb0ef41Sopenharmony_ci    elif tarfile.is_tarfile(packedfile):
791cb0ef41Sopenharmony_ci        with contextlib.closing(tarfile.TarFile.open(packedfile, 'r')) as icuzip:
801cb0ef41Sopenharmony_ci            print(' Extracting tarfile: %s' % packedfile)
811cb0ef41Sopenharmony_ci            icuzip.extractall(parent_path)
821cb0ef41Sopenharmony_ci            return parent_path
831cb0ef41Sopenharmony_ci    else:
841cb0ef41Sopenharmony_ci        packedsuffix = packedfile.lower().split('.')[-1]  # .zip, .tgz etc
851cb0ef41Sopenharmony_ci        raise Exception('Error: Don\'t know how to unpack %s with extension %s' % (packedfile, packedsuffix))
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci# List of possible "--download=" types.
881cb0ef41Sopenharmony_cidownload_types = set(['icu'])
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci# Default options for --download.
911cb0ef41Sopenharmony_cidownload_default = "none"
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_cidef help():
941cb0ef41Sopenharmony_ci  """This function calculates the '--help' text for '--download'."""
951cb0ef41Sopenharmony_ci  return """Select which packages may be auto-downloaded.
961cb0ef41Sopenharmony_civalid values are: none, all, %s. (default is "%s").""" % (", ".join(download_types), download_default)
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_cidef set2dict(keys, value=None):
991cb0ef41Sopenharmony_ci  """Convert some keys (iterable) to a dict."""
1001cb0ef41Sopenharmony_ci  return dict((key, value) for (key) in keys)
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_cidef parse(opt):
1031cb0ef41Sopenharmony_ci  """This function parses the options to --download and returns a set such as { icu: true }, etc. """
1041cb0ef41Sopenharmony_ci  if not opt:
1051cb0ef41Sopenharmony_ci    opt = download_default
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci  theOpts = set(opt.split(','))
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci  if 'all' in theOpts:
1101cb0ef41Sopenharmony_ci    # all on
1111cb0ef41Sopenharmony_ci    return set2dict(download_types, True)
1121cb0ef41Sopenharmony_ci  elif 'none' in theOpts:
1131cb0ef41Sopenharmony_ci    # all off
1141cb0ef41Sopenharmony_ci    return set2dict(download_types, False)
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci  # OK. Now, process each of the opts.
1171cb0ef41Sopenharmony_ci  theRet = set2dict(download_types, False)
1181cb0ef41Sopenharmony_ci  for anOpt in opt.split(','):
1191cb0ef41Sopenharmony_ci    if not anOpt or anOpt == "":
1201cb0ef41Sopenharmony_ci      # ignore stray commas, etc.
1211cb0ef41Sopenharmony_ci      continue
1221cb0ef41Sopenharmony_ci    elif anOpt == 'all':
1231cb0ef41Sopenharmony_ci      # all on
1241cb0ef41Sopenharmony_ci      theRet = dict((key, True) for (key) in download_types)
1251cb0ef41Sopenharmony_ci    else:
1261cb0ef41Sopenharmony_ci      # turn this one on
1271cb0ef41Sopenharmony_ci      if anOpt in download_types:
1281cb0ef41Sopenharmony_ci        theRet[anOpt] = True
1291cb0ef41Sopenharmony_ci      else:
1301cb0ef41Sopenharmony_ci        # future proof: ignore unknown types
1311cb0ef41Sopenharmony_ci        print('Warning: ignoring unknown --download= type "%s"' % anOpt)
1321cb0ef41Sopenharmony_ci  # all done
1331cb0ef41Sopenharmony_ci  return theRet
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_cidef candownload(auto_downloads, package):
1361cb0ef41Sopenharmony_ci  if not (package in auto_downloads.keys()):
1371cb0ef41Sopenharmony_ci    raise Exception('Internal error: "%s" is not in the --downloads list. Check nodedownload.py' % package)
1381cb0ef41Sopenharmony_ci  if auto_downloads[package]:
1391cb0ef41Sopenharmony_ci    return True
1401cb0ef41Sopenharmony_ci  else:
1411cb0ef41Sopenharmony_ci    print("""Warning: Not downloading package "%s". You could pass "--download=all"
1421cb0ef41Sopenharmony_ci    (Windows: "download-all") to try auto-downloading it.""" % package)
1431cb0ef41Sopenharmony_ci    return False
144