| # Copyright 2011-2015 The Rust Project Developers. See the COPYRIGHT |
| # file at the top-level directory of this distribution and at |
| # http://rust-lang.org/COPYRIGHT. |
| # |
| # Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
| # http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
| # <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
| # option. This file may not be copied, modified, or distributed |
| # except according to those terms. |
| |
| import re |
| import os |
| import sys |
| import glob |
| import tarfile |
| import shutil |
| import subprocess |
| import distutils.spawn |
| |
| try: |
| import hashlib |
| sha_func = hashlib.sha1 |
| except ImportError: |
| import sha |
| sha_func = sha.new |
| |
| |
| def scrub(b): |
| if sys.version_info >= (3,) and type(b) == bytes: |
| return b.decode('ascii') |
| else: |
| return b |
| |
| src_dir = scrub(os.getenv("CFG_SRC_DIR")) |
| if not src_dir: |
| raise Exception("missing env var CFG_SRC_DIR") |
| |
| snapshotfile = os.path.join(src_dir, "src", "snapshots.txt") |
| download_url_base = "https://static.rust-lang.org/stage0-snapshots" |
| download_dir_base = "dl" |
| download_unpack_base = os.path.join(download_dir_base, "unpack") |
| |
| snapshot_files = { |
| "bitrig": ["bin/rustc"], |
| "dragonfly": ["bin/rustc"], |
| "freebsd": ["bin/rustc"], |
| "linux": ["bin/rustc"], |
| "macos": ["bin/rustc"], |
| "netbsd": ["bin/rustc"], |
| "openbsd": ["bin/rustc"], |
| "winnt": ["bin/rustc.exe"], |
| } |
| |
| winnt_runtime_deps_32 = ["libgcc_s_dw2-1.dll", "libstdc++-6.dll"] |
| winnt_runtime_deps_64 = ["libgcc_s_seh-1.dll", "libstdc++-6.dll"] |
| |
| def parse_line(n, line): |
| global snapshotfile |
| |
| if re.match(r"\s*$", line): |
| return None |
| |
| if re.match(r"^T\s*$", line): |
| return None |
| |
| match = re.match(r"\s+([\w_-]+) ([a-fA-F\d]{40})\s*$", line) |
| if match: |
| return {"type": "file", |
| "platform": match.group(1), |
| "hash": match.group(2).lower()} |
| |
| match = re.match(r"([ST]) (\d{4}-\d{2}-\d{2}) ([a-fA-F\d]+)\s*$", line) |
| if not match: |
| raise Exception("%s:%d:E syntax error: " % (snapshotfile, n)) |
| return {"type": "snapshot", |
| "date": match.group(2), |
| "rev": match.group(3)} |
| |
| |
| def partial_snapshot_name(date, rev, platform): |
| return ("rust-stage0-%s-%s-%s.tar.bz2" % |
| (date, rev, platform)) |
| |
| |
| def full_snapshot_name(date, rev, platform, hsh): |
| return ("rust-stage0-%s-%s-%s-%s.tar.bz2" % |
| (date, rev, platform, hsh)) |
| |
| |
| def get_kernel(triple): |
| t = triple.split('-') |
| if len(t) == 2: |
| os_name = t[1] |
| else: |
| os_name = t[2] |
| |
| if os_name == "windows": |
| return "winnt" |
| if os_name == "darwin": |
| return "macos" |
| if os_name == "freebsd": |
| return "freebsd" |
| if os_name == "dragonfly": |
| return "dragonfly" |
| if os_name == "bitrig": |
| return "bitrig" |
| if os_name == "netbsd": |
| return "netbsd" |
| if os_name == "openbsd": |
| return "openbsd" |
| return "linux" |
| |
| |
| def get_cpu(triple): |
| arch = triple.split('-')[0] |
| if arch == "i686": |
| return "i386" |
| return arch |
| |
| |
| def get_platform(triple): |
| return "%s-%s" % (get_kernel(triple), get_cpu(triple)) |
| |
| |
| def cmd_out(cmdline): |
| p = subprocess.Popen(cmdline, stdout=subprocess.PIPE) |
| return scrub(p.communicate()[0].strip()) |
| |
| |
| def local_rev_info(field): |
| return cmd_out(["git", "--git-dir=" + os.path.join(src_dir, ".git"), |
| "log", "-n", "1", |
| "--format=%%%s" % field, "HEAD"]) |
| |
| |
| def local_rev_full_sha(): |
| return local_rev_info("H").split()[0] |
| |
| |
| def local_rev_short_sha(): |
| return local_rev_info("h").split()[0] |
| |
| |
| def local_rev_committer_date(): |
| return local_rev_info("ci") |
| |
| |
| def get_url_to_file(u, f): |
| # no security issue, just to stop partial download leaving a stale file |
| tmpf = f + '.tmp' |
| |
| returncode = -1 |
| if distutils.spawn.find_executable("curl"): |
| returncode = subprocess.call(["curl", "-o", tmpf, u]) |
| elif distutils.spawn.find_executable("wget"): |
| returncode = subprocess.call(["wget", "-O", tmpf, u]) |
| |
| if returncode != 0: |
| try: |
| os.unlink(tmpf) |
| except OSError: |
| pass |
| raise Exception("failed to fetch url") |
| os.rename(tmpf, f) |
| |
| |
| def snap_filename_hash_part(snap): |
| match = re.match(r".*([a-fA-F\d]{40}).tar.bz2$", snap) |
| if not match: |
| raise Exception("unable to find hash in filename: " + snap) |
| return match.group(1) |
| |
| |
| def hash_file(x): |
| h = sha_func() |
| h.update(open(x, "rb").read()) |
| return scrub(h.hexdigest()) |
| |
| |
| def get_winnt_runtime_deps(platform): |
| """Returns a list of paths of Rust's system runtime dependencies""" |
| if platform == "winnt-x86_64": |
| deps = winnt_runtime_deps_64 |
| else: |
| deps = winnt_runtime_deps_32 |
| runtime_deps = [] |
| path_dirs = os.environ["PATH"].split(os.pathsep) |
| for name in deps: |
| for dir in path_dirs: |
| filepath = os.path.join(dir, name) |
| if os.path.isfile(filepath): |
| runtime_deps.append(filepath) |
| break |
| else: |
| raise Exception("Could not find runtime dependency: %s" % name) |
| return runtime_deps |
| |
| |
| def make_snapshot(stage, triple): |
| kernel = get_kernel(triple) |
| platform = get_platform(triple) |
| rev = local_rev_short_sha() |
| date = local_rev_committer_date().split()[0] |
| |
| file0 = partial_snapshot_name(date, rev, platform) |
| |
| def in_tar_name(fn): |
| cs = re.split(r"[\\/]", fn) |
| if len(cs) >= 2: |
| return os.sep.join(cs[-2:]) |
| |
| tar = tarfile.open(file0, "w:bz2") |
| |
| for name in snapshot_files[kernel]: |
| dir = stage |
| if stage == "stage1" and re.match(r"^lib/(lib)?std.*", name): |
| dir = "stage0" |
| fn_glob = os.path.join(triple, dir, name) |
| matches = glob.glob(fn_glob) |
| if not matches: |
| raise Exception("Not found file with name like " + fn_glob) |
| if len(matches) == 1: |
| tar.add(matches[0], "rust-stage0/" + in_tar_name(matches[0])) |
| else: |
| raise Exception("Found stale files: \n %s\n" |
| "Please make a clean build." % "\n ".join(matches)) |
| |
| if kernel == "winnt": |
| for path in get_winnt_runtime_deps(platform): |
| tar.add(path, "rust-stage0/bin/" + os.path.basename(path)) |
| tar.add(os.path.join(os.path.dirname(__file__), "third-party"), |
| "rust-stage0/bin/third-party") |
| |
| tar.close() |
| |
| h = hash_file(file0) |
| file1 = full_snapshot_name(date, rev, platform, h) |
| |
| shutil.move(file0, file1) |
| |
| return file1 |
| |
| |
| def curr_snapshot_rev(): |
| i = 0 |
| found_snap = False |
| date = None |
| rev = None |
| |
| f = open(snapshotfile) |
| for line in f.readlines(): |
| i += 1 |
| parsed = parse_line(i, line) |
| if not parsed: |
| continue |
| |
| if parsed["type"] == "snapshot": |
| date = parsed["date"] |
| rev = parsed["rev"] |
| found_snap = True |
| break |
| |
| if not found_snap: |
| raise Exception("no snapshot entries in file") |
| |
| return (date, rev) |
| |
| |
| def determine_curr_snapshot(triple): |
| i = 0 |
| platform = get_platform(triple) |
| |
| found_file = False |
| found_snap = False |
| hsh = None |
| date = None |
| rev = None |
| |
| f = open(snapshotfile) |
| for line in f.readlines(): |
| i += 1 |
| parsed = parse_line(i, line) |
| if not parsed: |
| continue |
| |
| if found_snap and parsed["type"] == "file": |
| if parsed["platform"] == platform: |
| hsh = parsed["hash"] |
| found_file = True |
| break |
| elif parsed["type"] == "snapshot": |
| date = parsed["date"] |
| rev = parsed["rev"] |
| found_snap = True |
| |
| if not found_snap: |
| raise Exception("no snapshot entries in file") |
| |
| if not found_file: |
| raise Exception("no snapshot file found for platform %s, rev %s" % |
| (platform, rev)) |
| |
| return full_snapshot_name(date, rev, platform, hsh) |