| #!/usr/bin/env python3 |
| # |
| # Copyright 2022 Google LLC |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # https://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| """Download and install renode release package.""" |
| |
| import argparse |
| import os |
| import re |
| import sys |
| import time |
| import tarfile |
| import urllib |
| |
| from pathlib import Path |
| |
| import wget |
| |
| |
| def download_artifact(url, artifact_name, out_dir): |
| """Download the artifact from url.""" |
| if not os.path.isdir(out_dir): |
| os.makedirs(out_dir) |
| out_file = os.path.join(out_dir, artifact_name) |
| download_url = os.path.join(url, artifact_name) |
| num_retries = 3 |
| for i in range(num_retries + 1): |
| try: |
| wget.download(download_url, out=out_file) |
| break |
| except urllib.error.HTTPError as exception: |
| if i == num_retries: |
| raise |
| print(f"{exception}\nDownload failed. Retrying...") |
| time.sleep(5) |
| return out_file |
| |
| |
| def strip_top_directory(tar): |
| """Renode packages the release with a top directory. Need to strip it.""" |
| members = tar.getmembers() |
| out_members = [] |
| for member in members[1:]: |
| if member.path.startswith(members[0].name + "/"): |
| member.path = os.path.join( |
| *(member.name.split(os.path.sep)[1:])) |
| out_members.append(member) |
| |
| tag = re.search("(.+?)_portable", members[0].name).group(1) |
| return tag, out_members |
| |
| |
| def main(): |
| """Download and install renode release package.""" |
| pin_toolchains = os.getenv('PIN_TOOLCHAINS', '').lower().split(' ') |
| if "renode" in pin_toolchains: |
| print() |
| print("****************************************************") |
| print("* *") |
| print("* PIN_TOOLCHAINS includes renode! Skipping the *") |
| print("* download of the latest Renode binaries. *") |
| print("* PLEASE DON'T file bugs for Renode mis-behavior! *") |
| print("* *") |
| print("****************************************************") |
| print() |
| sys.exit(0) |
| |
| out_dir = os.getenv("OUT") |
| if not out_dir: |
| out_dir = "/tmp" |
| |
| parser = argparse.ArgumentParser( |
| description="Download Renode from Antmicro releases") |
| parser.add_argument( |
| "--release_name", action="store", default="", |
| help="Release to be downloaded. If not set, download the latest") |
| parser.add_argument( |
| "--release_url", |
| action="store", |
| default="https://dl.antmicro.com/projects/renode/builds/", |
| help=("URL to check the IREE release." |
| "(default: https://dl.antmicro.com/projects/renode/builds/)")) |
| parser.add_argument( |
| "--renode_dir", action="store", required=True, |
| default="", |
| help=("Renode installed directory") |
| ) |
| |
| args = parser.parse_args() |
| |
| with urllib.request.urlopen(args.release_url + '?C=M;O=D') as website: |
| html_list = website.read().decode("utf-8") |
| files = re.findall(r'href="(renode-.*git.*\.linux-portable\.tar\.gz)"', |
| html_list) |
| |
| release_found = False |
| release_name = None |
| if args.release_name: |
| for file in files: |
| if args.release_name in file: |
| release_found = True |
| release_name = re.search( |
| "(.+?).linux-portable.tar.gz", file).group(1) |
| break |
| else: |
| # The latest nightly release is the symlink of the first entry. |
| release_found = True |
| release_name = re.search("(.+?).linux-portable.tar.gz", |
| files[0]).group(1) |
| |
| if not release_found: |
| print(f"!!!!!Renode can't be found with release {args.release_name}, " |
| "please try a different release!!!!!") |
| sys.exit(1) |
| |
| print(f"Release: {release_name}") |
| commit_sha = re.search("git(.+?)$", release_name).group(1) |
| |
| renode_dir = Path(args.renode_dir) |
| if not os.path.isdir(renode_dir): |
| os.makedirs(renode_dir) |
| tag_file = renode_dir / "tag" |
| |
| # Check the tag of the existing download. |
| release_match = False |
| built_from_src = False |
| if os.path.isfile(tag_file): |
| with open(tag_file, "r", encoding="utf-8") as file: |
| for line in file: |
| if "built_from_src" in line.replace("\n", ""): |
| built_from_src = True |
| break |
| if commit_sha in line.replace("\n", ""): |
| release_match = True |
| break |
| if built_from_src: |
| print("Renode was built from the source. run `m renode_clean` if you " |
| "want to download the nightly release.") |
| sys.exit(0) |
| if release_match: |
| print("Renode is up-to-date") |
| sys.exit(0) |
| |
| tmp_dir = Path(out_dir) / "tmp" |
| artifact_name = release_name + ".linux-portable.tar.gz" |
| tar_file = download_artifact(args.release_url, artifact_name, tmp_dir) |
| |
| # Extract the tarball |
| with tarfile.open(tar_file) as tar: |
| _, members = strip_top_directory(tar) |
| tar.extractall(members=members, path=renode_dir) |
| |
| os.remove(tar_file) |
| print("\nRenode is installed") |
| |
| # Add tag file for future checks |
| with open(tag_file, "w", encoding="utf-8") as file: |
| file.write(f"{release_name}\ncommit_sha: {commit_sha}\n") |
| |
| |
| if __name__ == "__main__": |
| main() |