/src/etc/snapshot.py

http://github.com/jruderman/rust · Python · 214 lines · 166 code · 45 blank · 3 comment · 29 complexity · 9eab4e52dbe36492b2b910606566c7ab MD5 · raw file

  1. import re, os, sys, glob, tarfile, shutil, subprocess, tempfile
  2. try:
  3. import hashlib
  4. sha_func = hashlib.sha1
  5. except ImportError:
  6. import sha
  7. sha_func = sha.new
  8. def scrub(b):
  9. if sys.version_info >= (3,) and type(b) == bytes:
  10. return b.decode('ascii')
  11. else:
  12. return b
  13. src_dir = scrub(os.getenv("CFG_SRC_DIR"))
  14. if not src_dir:
  15. raise Exception("missing env var CFG_SRC_DIR")
  16. snapshotfile = os.path.join(src_dir, "src", "snapshots.txt")
  17. download_url_base = "http://dl.rust-lang.org/stage0-snapshots"
  18. download_dir_base = "dl"
  19. download_unpack_base = os.path.join(download_dir_base, "unpack")
  20. snapshot_files = {
  21. "linux": ["bin/rustc",
  22. "lib/libcore-*.so",
  23. "lib/libstd-*.so",
  24. "lib/librustc-*.so",
  25. "lib/libsyntax-*.so",
  26. "lib/librustrt.so",
  27. "lib/librustllvm.so"],
  28. "macos": ["bin/rustc",
  29. "lib/libcore-*.dylib",
  30. "lib/libstd-*.dylib",
  31. "lib/librustc-*.dylib",
  32. "lib/libsyntax-*.dylib",
  33. "lib/librustrt.dylib",
  34. "lib/librustllvm.dylib"],
  35. "winnt": ["bin/rustc.exe",
  36. "bin/core-*.dll",
  37. "bin/std-*.dll",
  38. "bin/rustc-*.dll",
  39. "bin/syntax-*.dll",
  40. "bin/rustrt.dll",
  41. "bin/rustllvm.dll"],
  42. "freebsd": ["bin/rustc",
  43. "lib/libcore-*.so",
  44. "lib/libstd-*.so",
  45. "lib/librustc-*.so",
  46. "lib/libsyntax-*.so",
  47. "lib/librustrt.so",
  48. "lib/librustllvm.so"]
  49. }
  50. def parse_line(n, line):
  51. global snapshotfile
  52. if re.match(r"\s*$", line): return None
  53. if re.match(r"^T\s*$", line): return None
  54. match = re.match(r"\s+([\w_-]+) ([a-fA-F\d]{40})\s*$", line)
  55. if match:
  56. return { "type": "file",
  57. "platform": match.group(1),
  58. "hash": match.group(2).lower() }
  59. match = re.match(r"([ST]) (\d{4}-\d{2}-\d{2}) ([a-fA-F\d]+)\s*$", line);
  60. if (not match):
  61. raise Exception("%s:%d:E syntax error" % (snapshotfile, n))
  62. return {"type": "snapshot",
  63. "date": match.group(2),
  64. "rev": match.group(3)}
  65. def partial_snapshot_name(date, rev, platform):
  66. return ("rust-stage0-%s-%s-%s.tar.bz2"
  67. % (date, rev, platform))
  68. def full_snapshot_name(date, rev, platform, hsh):
  69. return ("rust-stage0-%s-%s-%s-%s.tar.bz2"
  70. % (date, rev, platform, hsh))
  71. def get_kernel(triple):
  72. os_name = triple.split('-')[-1]
  73. #scrub(os.getenv("CFG_ENABLE_MINGW_CROSS")):
  74. if os_name == "nt" or os_name == "mingw32":
  75. return "winnt"
  76. if os_name == "darwin":
  77. return "macos"
  78. if os_name == "freebsd":
  79. return "freebsd"
  80. return "linux"
  81. def get_cpu(triple):
  82. arch = triple.split('-')[0]
  83. if arch == "i686":
  84. return "i386"
  85. return arch
  86. def get_platform(triple):
  87. return "%s-%s" % (get_kernel(triple), get_cpu(triple))
  88. def cmd_out(cmdline):
  89. p = subprocess.Popen(cmdline,
  90. stdout=subprocess.PIPE)
  91. return scrub(p.communicate()[0].strip())
  92. def local_rev_info(field):
  93. return cmd_out(["git", "--git-dir=" + os.path.join(src_dir, ".git"),
  94. "log", "-n", "1",
  95. "--format=%%%s" % field, "HEAD"])
  96. def local_rev_full_sha():
  97. return local_rev_info("H").split()[0]
  98. def local_rev_short_sha():
  99. return local_rev_info("h").split()[0]
  100. def local_rev_committer_date():
  101. return local_rev_info("ci")
  102. def get_url_to_file(u,f):
  103. # no security issue, just to stop partial download leaving a stale file
  104. tmpf = f + '.tmp'
  105. returncode = subprocess.call(["curl", "-o", tmpf, u])
  106. if returncode != 0:
  107. os.unlink(tmpf)
  108. raise
  109. os.rename(tmpf, f)
  110. def snap_filename_hash_part(snap):
  111. match = re.match(r".*([a-fA-F\d]{40}).tar.bz2$", snap)
  112. if not match:
  113. raise Exception("unable to find hash in filename: " + snap)
  114. return match.group(1)
  115. def hash_file(x):
  116. h = sha_func()
  117. h.update(open(x, "rb").read())
  118. return scrub(h.hexdigest())
  119. def make_snapshot(stage, triple, flag):
  120. kernel = get_kernel(triple)
  121. platform = get_platform(triple)
  122. rev = local_rev_short_sha()
  123. date = local_rev_committer_date().split()[0]
  124. file0 = partial_snapshot_name(date, rev, platform)
  125. def in_tar_name(fn):
  126. cs = re.split(r"[\\/]", fn)
  127. if len(cs) >= 2:
  128. return os.sep.join(cs[-2:])
  129. tar = tarfile.open(file0, "w:bz2")
  130. for name in snapshot_files[kernel]:
  131. dir = stage
  132. if stage == "stage1" and re.match(r"^lib/(lib)?std.*", name):
  133. dir = "stage0"
  134. fn_glob = os.path.join(triple, dir, name)
  135. matches = glob.glob(fn_glob)
  136. if not matches:
  137. raise Exception("Not found file with name like " + fn_glob)
  138. if len(matches) == 1:
  139. tar.add(matches[0], "rust-stage0/" + in_tar_name(matches[0]))
  140. else:
  141. raise Exception("Found stale files: \n %s\n\
  142. Please make a clean build." % "\n ".join(matches))
  143. tar.close()
  144. h = hash_file(file0)
  145. file1 = full_snapshot_name(date, rev, platform, h)
  146. shutil.move(file0, file1)
  147. if flag == "install":
  148. # FIXME (#2664): this is an ugly quick hack; pls make it better
  149. path = file1
  150. comps = path.split("-")
  151. parts = { 'year': comps[2], \
  152. 'month': comps[3], \
  153. 'date': comps[4], \
  154. 'check': comps[5], \
  155. 'plat': comps[6], \
  156. 'arch': comps[7], \
  157. 'sha': comps[8].split(".")[0] }
  158. shutil.move(path, "dl/" + path)
  159. shutil.move('src/snapshots.txt', 'src/snapshots-old.txt')
  160. newf = open('src/snapshots.txt', 'w')
  161. newf.write("T %(year)s-%(month)s-%(date)s %(check)s\n" % parts)
  162. newf.write(" %(plat)s-%(arch)s %(sha)s\n\n" % parts)
  163. oldf = open('src/snapshots-old.txt', 'r')
  164. for line in oldf:
  165. newf.write(line)
  166. oldf.close()
  167. newf.close()
  168. os.remove('src/snapshots-old.txt')
  169. return file1