get.py 5.8 KB
Newer Older
M
me-no-dev 已提交
1
#!/usr/bin/env python
2 3 4 5 6 7 8

"""Script to download and extract tools

This script will download and extract required tools into the current directory.
Tools list is obtained from package/package_esp8266com_index.template.json file.
"""

M
me-no-dev 已提交
9
from __future__ import print_function
10 11 12 13

__author__ = "Ivan Grokhotkov"
__version__ = "2015"

M
me-no-dev 已提交
14 15 16 17 18 19 20 21 22 23 24
import os
import shutil
import errno
import os.path
import hashlib
import json
import platform
import sys
import tarfile
import zipfile
import re
25

M
me-no-dev 已提交
26 27
if sys.version_info[0] == 3:
    from urllib.request import urlretrieve
M
me-no-dev 已提交
28
    from urllib.request import urlopen
29
    unicode = lambda s: str(s)
M
me-no-dev 已提交
30 31 32
else:
    # Not Python 3 - today, it is most likely to be Python 2
    from urllib import urlretrieve
M
me-no-dev 已提交
33
    from urllib import urlopen
M
me-no-dev 已提交
34

M
me-no-dev 已提交
35 36 37
if 'Windows' in platform.system():
    import requests

P
Patas007 已提交
38
current_dir = os.path.dirname(os.path.realpath(unicode(__file__)))
M
me-no-dev 已提交
39
dist_dir = current_dir + '/dist/'
M
me-no-dev 已提交
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

def sha256sum(filename, blocksize=65536):
    hash = hashlib.sha256()
    with open(filename, "rb") as f:
        for block in iter(lambda: f.read(blocksize), b""):
            hash.update(block)
    return hash.hexdigest()

def mkdir_p(path):
    try:
        os.makedirs(path)
    except OSError as exc:
        if exc.errno != errno.EEXIST or not os.path.isdir(path):
            raise

def report_progress(count, blockSize, totalSize):
    percent = int(count*blockSize*100/totalSize)
    percent = min(100, percent)
    sys.stdout.write("\r%d%%" % percent)
    sys.stdout.flush()

def unpack(filename, destination):
    dirname = ''
M
me-no-dev 已提交
63 64
    print('Extracting {0}'.format(os.path.basename(filename)))
    sys.stdout.flush()
M
me-no-dev 已提交
65 66 67
    if filename.endswith('tar.gz'):
        tfile = tarfile.open(filename, 'r:gz')
        tfile.extractall(destination)
68
        dirname = tfile.getnames()[0]
M
me-no-dev 已提交
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
    elif filename.endswith('zip'):
        zfile = zipfile.ZipFile(filename)
        zfile.extractall(destination)
        dirname = zfile.namelist()[0]
    else:
        raise NotImplementedError('Unsupported archive type')

    # a little trick to rename tool directories so they don't contain version number
    rename_to = re.match(r'^([a-z][^\-]*\-*)+', dirname).group(0).strip('-')
    if rename_to != dirname:
        print('Renaming {0} to {1}'.format(dirname, rename_to))
        if os.path.isdir(rename_to):
            shutil.rmtree(rename_to)
        shutil.move(dirname, rename_to)

M
me-no-dev 已提交
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
def download_file(url,filename):
    import ssl
    import contextlib
    ctx = ssl.create_default_context()
    ctx.check_hostname = False
    ctx.verify_mode = ssl.CERT_NONE
    with contextlib.closing(urlopen(url,context=ctx)) as fp:
        block_size = 1024 * 8
        block = fp.read(block_size)
        if block:
            with open(filename,'wb') as out_file:
                out_file.write(block)
                while True:
                    block = fp.read(block_size)
                    if not block:
                        break
                    out_file.write(block)
        else:
            raise Exception ('nonexisting file or connection error')

M
me-no-dev 已提交
104
def get_tool(tool):
M
me-no-dev 已提交
105
    sys_name = platform.system()
M
me-no-dev 已提交
106 107 108 109 110
    archive_name = tool['archiveFileName']
    local_path = dist_dir + archive_name
    url = tool['url']
    #real_hash = tool['checksum'].split(':')[1]
    if not os.path.isfile(local_path):
111
        print('Downloading ' + archive_name)
M
me-no-dev 已提交
112
        sys.stdout.flush()
M
me-no-dev 已提交
113
        if 'CYGWIN_NT' in sys_name:
M
me-no-dev 已提交
114
            import ssl
M
me-no-dev 已提交
115 116 117 118 119 120 121 122 123
            ctx = ssl.create_default_context()
            ctx.check_hostname = False
            ctx.verify_mode = ssl.CERT_NONE
            urlretrieve(url, local_path, report_progress, context=ctx)
        elif 'Windows' in sys_name:
            r = requests.get(url)
            f = open(local_path, 'wb')
            f.write(r.content)
            f.close()
M
me-no-dev 已提交
124
        else:
M
me-no-dev 已提交
125 126 127 128 129
            is_ci = os.environ.get('TRAVIS_BUILD_DIR');
            if is_ci:
                download_file(url, local_path)
            else:
                urlretrieve(url, local_path, report_progress)
M
me-no-dev 已提交
130 131 132 133
        sys.stdout.write("\rDone\n")
        sys.stdout.flush()
    else:
        print('Tool {0} already downloaded'.format(archive_name))
M
me-no-dev 已提交
134
        sys.stdout.flush()
M
me-no-dev 已提交
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
    #local_hash = sha256sum(local_path)
    #if local_hash != real_hash:
    #    print('Hash mismatch for {0}, delete the file and try again'.format(local_path))
    #    raise RuntimeError()
    unpack(local_path, '.')

def load_tools_list(filename, platform):
    tools_info = json.load(open(filename))['packages'][0]['tools']
    tools_to_download = []
    for t in tools_info:
        tool_platform = [p for p in t['systems'] if p['host'] == platform]
        if len(tool_platform) == 0:
            continue
        tools_to_download.append(tool_platform[0])
    return tools_to_download

def identify_platform():
    arduino_platform_names = {'Darwin'  : {32 : 'i386-apple-darwin',   64 : 'x86_64-apple-darwin'},
                              'Linux'   : {32 : 'i686-pc-linux-gnu',   64 : 'x86_64-pc-linux-gnu'},
                              'LinuxARM': {32 : 'arm-linux-gnueabihf', 64 : 'aarch64-linux-gnu'},
                              'Windows' : {32 : 'i686-mingw32',        64 : 'i686-mingw32'}}
    bits = 32
    if sys.maxsize > 2**32:
        bits = 64
    sys_name = platform.system()
M
me-no-dev 已提交
160 161 162
    sys_platform = platform.platform()
    print('System: %s, Info: %s' % (sys_name, sys_platform))
    if 'Linux' in sys_name and sys_platform.find('arm') > 0:
M
me-no-dev 已提交
163 164 165 166 167 168
        sys_name = 'LinuxARM'
    if 'CYGWIN_NT' in sys_name:
        sys_name = 'Windows'
    return arduino_platform_names[sys_name][bits]

if __name__ == '__main__':
M
me-no-dev 已提交
169 170 171
    identified_platform = identify_platform()
    print('Platform: {0}'.format(identified_platform))
    tools_to_download = load_tools_list(current_dir + '/../package/package_esp32_index.template.json', identified_platform)
M
me-no-dev 已提交
172 173 174
    mkdir_p(dist_dir)
    for tool in tools_to_download:
        get_tool(tool)
M
me-no-dev 已提交
175
    print('Done')