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