forked from electron/electron
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathupdate-external-binaries.py
executable file
·135 lines (97 loc) · 3.58 KB
/
update-external-binaries.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
#!/usr/bin/env python
import argparse
import errno
import hashlib
import json
import os
import tarfile
from lib.config import PLATFORM, get_target_arch
from lib.util import add_exec_bit, download, extract_zip, rm_rf, \
safe_mkdir, tempdir
SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
CONFIG_PATH = os.path.join(SOURCE_ROOT, 'script', 'external-binaries.json')
def parse_args():
parser = argparse.ArgumentParser(
description='Download binaries for Electron build')
parser.add_argument('--base-url', required=False,
help="Base URL for all downloads")
parser.add_argument('--force', action='store_true', default=False, required=False)
return parser.parse_args()
def parse_config():
with open(CONFIG_PATH, 'r') as config_file:
config = json.load(config_file)
return config
def main():
args = parse_args()
config = parse_config()
base_url = args.base_url if args.base_url is not None else config['baseUrl']
output_dir = os.path.join(SOURCE_ROOT, 'external_binaries')
config_hash_path = os.path.join(output_dir, '.hash')
if (not is_updated(config_hash_path) and not args.force):
return
rm_rf(output_dir)
safe_mkdir(output_dir)
for binary in config['files']:
if not binary_should_be_downloaded(binary):
continue
temp_path = download_binary(base_url, binary['sha'], binary['name'])
if temp_path.endswith('.zip'):
extract_zip(temp_path, output_dir)
else:
tar = tarfile.open(temp_path, "r:gz")
tar.extractall(output_dir)
tar.close()
# Hack alert. Set exec bit for sccache binaries.
# https://bugs.python.org/issue15795
if 'sccache' in binary['name']:
add_exec_bit_to_sccache_binary(output_dir)
with open(config_hash_path, 'w') as f:
f.write(sha256(CONFIG_PATH))
def is_updated(config_hash_path):
existing_hash = ''
try:
with open(config_hash_path, 'r') as f:
existing_hash = f.readline().strip()
except IOError as e:
if e.errno != errno.ENOENT:
raise
return not sha256(CONFIG_PATH) == existing_hash
def binary_should_be_downloaded(binary):
if 'platform' in binary and binary['platform'] != PLATFORM:
return False
if 'targetArch' in binary and binary['targetArch'] != get_target_arch():
return False
return True
def sha256(file_path):
hash_256 = hashlib.sha256()
with open(file_path, "rb") as f:
for chunk in iter(lambda: f.read(4096), b""):
hash_256.update(chunk)
return hash_256.hexdigest()
def download_binary(base_url, sha, binary_name, attempt=3):
full_url = '{0}/{1}/{2}'.format(base_url, sha, binary_name)
try:
temp_path = download_to_temp_dir(full_url, filename=binary_name, sha=sha)
return temp_path
except Exception as e:
if attempt == 1:
raise e
return download_binary(base_url, sha, binary_name, attempt - 1)
def validate_sha(file_path, sha):
downloaded_sha = sha256(file_path)
if downloaded_sha != sha:
raise Exception("SHA for external binary file {} does not match expected '{}' != '{}'".format(file_path, downloaded_sha, sha))
def download_to_temp_dir(url, filename, sha):
download_dir = tempdir(prefix='electron-')
file_path = os.path.join(download_dir, filename)
download(text='Download ' + filename, url=url, path=file_path)
validate_sha(file_path, sha)
return file_path
def add_exec_bit_to_sccache_binary(binary_dir):
binary_name = 'sccache'
if PLATFORM == 'win32':
binary_name += '.exe'
binary_path = os.path.join(binary_dir, binary_name)
add_exec_bit(binary_path)
if __name__ == '__main__':
main()