import os import sys import re import requests import shutil from subprocess import check_call from collections import defaultdict from pathlib import Path # Exall is an exception manager based on decorator/context/callback # Check it out: https://github.com/nongiach/exall from exall import exall, ignore from pySmartDL import SmartDL from .config import Config from .utils import pred @exall(os.mkdir, FileExistsError, ignore) def download(url, filename, cache_directory): filename_cache = url.split('/')[-1] filename_cache = ''.join([c for c in filename_cache if c.isdigit() or c.isalpha()]) filename_cache = cache_directory + "/" + filename_cache if os.path.exists(filename): return elif os.path.exists(filename_cache): print("Already downloaded") shutil.copyfile(filename_cache, filename) else: print("\nDownloading {} from {}".format(filename, url)) os.mkdir(cache_directory) # wget.download(url, out=filename_cache) obj = SmartDL(url, filename_cache) obj.start() shutil.copyfile(filename_cache, filename) def scrawl_kernel(arch): re_href = re.compile('href="?({arch}[^ <>"]*)"?'.format(arch=arch)) url = "https://toolchains.bootlin.com/downloads/releases/toolchains/{arch}/test-system/".format(arch=arch) response = requests.get(url + "?C=M;O=D") text = response.text links = re_href.findall(text) links_dict = defaultdict(lambda: defaultdict(dict)) for link in links: version = get_link_version(link) libc = get_link_libc(link) filetype = get_link_filetype(link) # TODO: make sure they have been compiled at the same time if filetype not in links_dict[version][libc]: if filetype is None: return None, None, None links_dict[version][libc][filetype] = url + link state = "bleeding-edge" if "stable" in links_dict: state = "stable" for libc in ["glibc", "uclibc", "musl"]: if libc in links_dict[state]: break else: libc = None target = links_dict[state][libc] dtb = target.get("dtb", None) rootfs = target.get("rootfs", None) kernel = target.get("kernel", None) return kernel, dtb, rootfs def indexof_parse(url): re_href = re.compile('\[DIR\].*href="?([^ <>"]*)"?') response = requests.get(url) text = response.text links = re_href.findall(text) return links libc = ["uclibc", "glibc", "musl"] def get_link_libc(link): for i_libc in libc: if i_libc in link: return i_libc return None def get_link_version(link): if "bleeding-edge" in link: return "bleeding-edge" else: return "stable" def get_link_filetype(link): if ".cpio" in link or ".ext2" in link or "rootfs" in link: return "rootfs" elif "dtb" in link: return "dtb" elif "Image" in link or "vmlinux" in link or "linux.bin" in link: return "kernel" print("ERROR: I don't know this kind of file {}".format(link), file=sys.stderr) # os.kill(0, 9) return None @exall(os.mkdir, FileExistsError, ignore) def download_from_github(arch): templates = str(Path.home()) + "/.config/arm_now/templates/" os.makedirs(templates) filename = arch + ".tar.xz" URL = "https://github.com/nongiach/arm_now_templates/raw/master/" download(URL + filename, templates + filename, Config.DOWNLOAD_CACHE_DIR) def download_image(arch, *, dest, real_source): if real_source: kernel, dtb, rootfs = scrawl_kernel(arch) if kernel is None or rootfs is None: pred("ERROR: couldn't download files for this arch", file=sys.stderr) sys.exit(1) download(kernel, dest + Config.kernel, Config.DOWNLOAD_CACHE_DIR) if dtb: download(dtb, dest + Config.dtb, Config.DOWNLOAD_CACHE_DIR) download(rootfs, dest + Config.rootfs, Config.DOWNLOAD_CACHE_DIR) else: download_from_github(arch) check_call("tar xf ~/.config/arm_now/templates/{}.tar.xz {}".format(arch, dest), shell=True) with open(dest + "/arch", "w") as F: F.write(arch)