Skip to content

Commit 81f511c

Browse files
committed
Move beta rustfmt downloads to rustbuild
1 parent bd6409d commit 81f511c

File tree

6 files changed

+153
-95
lines changed

6 files changed

+153
-95
lines changed

src/bootstrap/bootstrap.py

+21-63
Original file line numberDiff line numberDiff line change
@@ -63,31 +63,30 @@ def support_xz():
6363
except tarfile.CompressionError:
6464
return False
6565

66-
def get(base, url, path, checksums, verbose=False, do_verify=True):
66+
def get(base, url, path, checksums, verbose=False):
6767
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
6868
temp_path = temp_file.name
6969

7070
try:
71-
if do_verify:
72-
if url not in checksums:
73-
raise RuntimeError(("src/stage0.json doesn't contain a checksum for {}. "
74-
"Pre-built artifacts might not available for this "
75-
"target at this time, see https://doc.rust-lang.org/nightly"
76-
"/rustc/platform-support.html for more information.")
77-
.format(url))
78-
sha256 = checksums[url]
79-
if os.path.exists(path):
80-
if verify(path, sha256, False):
81-
if verbose:
82-
print("using already-download file", path)
83-
return
84-
else:
85-
if verbose:
86-
print("ignoring already-download file",
87-
path, "due to failed verification")
88-
os.unlink(path)
71+
if url not in checksums:
72+
raise RuntimeError(("src/stage0.json doesn't contain a checksum for {}. "
73+
"Pre-built artifacts might not be available for this "
74+
"target at this time, see https://doc.rust-lang.org/nightly"
75+
"/rustc/platform-support.html for more information.")
76+
.format(url))
77+
sha256 = checksums[url]
78+
if os.path.exists(path):
79+
if verify(path, sha256, False):
80+
if verbose:
81+
print("using already-download file", path)
82+
return
83+
else:
84+
if verbose:
85+
print("ignoring already-download file",
86+
path, "due to failed verification")
87+
os.unlink(path)
8988
download(temp_path, "{}/{}".format(base, url), True, verbose)
90-
if do_verify and not verify(temp_path, sha256, verbose):
89+
if not verify(temp_path, sha256, verbose):
9190
raise RuntimeError("failed verification")
9291
if verbose:
9392
print("moving {} to {}".format(temp_path, path))
@@ -430,7 +429,6 @@ class RustBuild(object):
430429
def __init__(self):
431430
self.checksums_sha256 = {}
432431
self.stage0_compiler = None
433-
self.stage0_rustfmt = None
434432
self._download_url = ''
435433
self.build = ''
436434
self.build_dir = ''
@@ -484,31 +482,10 @@ def download_toolchain(self):
484482
with output(self.rustc_stamp()) as rust_stamp:
485483
rust_stamp.write(key)
486484

487-
if self.rustfmt() and self.rustfmt().startswith(bin_root) and (
488-
not os.path.exists(self.rustfmt())
489-
or self.program_out_of_date(
490-
self.rustfmt_stamp(),
491-
"" if self.stage0_rustfmt is None else self.stage0_rustfmt.channel()
492-
)
493-
):
494-
if self.stage0_rustfmt is not None:
495-
tarball_suffix = '.tar.xz' if support_xz() else '.tar.gz'
496-
filename = "rustfmt-{}-{}{}".format(
497-
self.stage0_rustfmt.version, self.build, tarball_suffix,
498-
)
499-
self._download_component_helper(
500-
filename, "rustfmt-preview", tarball_suffix, key=self.stage0_rustfmt.date
501-
)
502-
self.fix_bin_or_dylib("{}/bin/rustfmt".format(bin_root))
503-
self.fix_bin_or_dylib("{}/bin/cargo-fmt".format(bin_root))
504-
with output(self.rustfmt_stamp()) as rustfmt_stamp:
505-
rustfmt_stamp.write(self.stage0_rustfmt.channel())
506-
507485
def _download_component_helper(
508-
self, filename, pattern, tarball_suffix, key=None
486+
self, filename, pattern, tarball_suffix,
509487
):
510-
if key is None:
511-
key = self.stage0_compiler.date
488+
key = self.stage0_compiler.date
512489
cache_dst = os.path.join(self.build_dir, "cache")
513490
rustc_cache = os.path.join(cache_dst, key)
514491
if not os.path.exists(rustc_cache):
@@ -524,7 +501,6 @@ def _download_component_helper(
524501
tarball,
525502
self.checksums_sha256,
526503
verbose=self.verbose,
527-
do_verify=True,
528504
)
529505
unpack(tarball, tarball_suffix, self.bin_root(), match=pattern, verbose=self.verbose)
530506

@@ -634,16 +610,6 @@ def rustc_stamp(self):
634610
"""
635611
return os.path.join(self.bin_root(), '.rustc-stamp')
636612

637-
def rustfmt_stamp(self):
638-
"""Return the path for .rustfmt-stamp
639-
640-
>>> rb = RustBuild()
641-
>>> rb.build_dir = "build"
642-
>>> rb.rustfmt_stamp() == os.path.join("build", "stage0", ".rustfmt-stamp")
643-
True
644-
"""
645-
return os.path.join(self.bin_root(), '.rustfmt-stamp')
646-
647613
def program_out_of_date(self, stamp_path, key):
648614
"""Check if the given program stamp is out of date"""
649615
if not os.path.exists(stamp_path) or self.clean:
@@ -717,12 +683,6 @@ def rustc(self):
717683
"""Return config path for rustc"""
718684
return self.program_config('rustc')
719685

720-
def rustfmt(self):
721-
"""Return config path for rustfmt"""
722-
if self.stage0_rustfmt is None:
723-
return None
724-
return self.program_config('rustfmt')
725-
726686
def program_config(self, program):
727687
"""Return config path for the given program at the given stage
728688
@@ -1082,8 +1042,6 @@ def bootstrap(help_triggered):
10821042
data = json.load(f)
10831043
build.checksums_sha256 = data["checksums_sha256"]
10841044
build.stage0_compiler = Stage0Toolchain(data["compiler"])
1085-
if data.get("rustfmt") is not None:
1086-
build.stage0_rustfmt = Stage0Toolchain(data["rustfmt"])
10871045

10881046
build.set_dist_environment(data["dist_server"])
10891047

src/bootstrap/builder.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -728,7 +728,8 @@ impl<'a> Builder<'a> {
728728
Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]),
729729
Subcommand::Install { ref paths } => (Kind::Install, &paths[..]),
730730
Subcommand::Run { ref paths } => (Kind::Run, &paths[..]),
731-
Subcommand::Format { .. } | Subcommand::Clean { .. } | Subcommand::Setup { .. } => {
731+
Subcommand::Format { .. } => (Kind::Format, &[][..]),
732+
Subcommand::Clean { .. } | Subcommand::Setup { .. } => {
732733
panic!()
733734
}
734735
};
@@ -1192,6 +1193,10 @@ impl<'a> Builder<'a> {
11921193
Config::download_rustc(self)
11931194
}
11941195

1196+
pub(crate) fn initial_rustfmt(&self) -> Option<PathBuf> {
1197+
Config::initial_rustfmt(self)
1198+
}
1199+
11951200
/// Prepares an invocation of `cargo` to be run.
11961201
///
11971202
/// This will create a `Command` that represents a pending execution of

src/bootstrap/config.rs

+116-17
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! This module implements parsing `config.toml` configuration files to tweak
44
//! how the build runs.
55
6-
use std::cell::Cell;
6+
use std::cell::{Cell, RefCell};
77
use std::cmp;
88
use std::collections::{HashMap, HashSet};
99
use std::env;
@@ -204,10 +204,27 @@ pub struct Config {
204204
// These are either the stage0 downloaded binaries or the locally installed ones.
205205
pub initial_cargo: PathBuf,
206206
pub initial_rustc: PathBuf,
207-
pub initial_rustfmt: Option<PathBuf>,
207+
#[cfg(not(test))]
208+
initial_rustfmt: RefCell<RustfmtState>,
209+
#[cfg(test)]
210+
pub initial_rustfmt: RefCell<RustfmtState>,
208211
pub out: PathBuf,
209212
}
210213

214+
#[derive(Clone, Debug)]
215+
pub enum RustfmtState {
216+
SystemToolchain(PathBuf),
217+
Downloaded(PathBuf),
218+
Unavailable,
219+
LazyEvaluated,
220+
}
221+
222+
impl Default for RustfmtState {
223+
fn default() -> Self {
224+
RustfmtState::LazyEvaluated
225+
}
226+
}
227+
211228
#[derive(Debug, Clone, Copy, PartialEq)]
212229
pub enum LlvmLibunwind {
213230
No,
@@ -1151,13 +1168,22 @@ impl Config {
11511168
set(&mut config.missing_tools, t.missing_tools);
11521169
}
11531170

1154-
config.initial_rustfmt = build.rustfmt.or_else(|| {
1155-
// Cargo does not provide a RUSTFMT environment variable, so we
1156-
// synthesize it manually.
1157-
let rustfmt = config.initial_rustc.with_file_name(exe("rustfmt", config.build));
1158-
1159-
if rustfmt.exists() { Some(rustfmt) } else { None }
1160-
});
1171+
if let Some(r) = build.rustfmt {
1172+
*config.initial_rustfmt.borrow_mut() = if r.exists() {
1173+
RustfmtState::SystemToolchain(r)
1174+
} else {
1175+
RustfmtState::Unavailable
1176+
};
1177+
} else {
1178+
// If using a system toolchain for bootstrapping, see if that has rustfmt available.
1179+
let host = config.build;
1180+
let rustfmt_path = config.initial_rustc.with_file_name(exe("rustfmt", host));
1181+
let bin_root = config.out.join(host.triple).join("stage0");
1182+
if !rustfmt_path.starts_with(&bin_root) {
1183+
// Using a system-provided toolchain; we shouldn't download rustfmt.
1184+
*config.initial_rustfmt.borrow_mut() = RustfmtState::SystemToolchain(rustfmt_path);
1185+
}
1186+
}
11611187

11621188
// Now that we've reached the end of our configuration, infer the
11631189
// default values for all options that we haven't otherwise stored yet.
@@ -1327,6 +1353,25 @@ impl Config {
13271353
})
13281354
}
13291355

1356+
pub(crate) fn initial_rustfmt(builder: &Builder<'_>) -> Option<PathBuf> {
1357+
match &mut *builder.config.initial_rustfmt.borrow_mut() {
1358+
RustfmtState::SystemToolchain(p) | RustfmtState::Downloaded(p) => Some(p.clone()),
1359+
RustfmtState::Unavailable => None,
1360+
r @ RustfmtState::LazyEvaluated => {
1361+
if builder.config.dry_run {
1362+
return Some(PathBuf::new());
1363+
}
1364+
let path = maybe_download_rustfmt(builder);
1365+
*r = if let Some(p) = &path {
1366+
RustfmtState::Downloaded(p.clone())
1367+
} else {
1368+
RustfmtState::Unavailable
1369+
};
1370+
path
1371+
}
1372+
}
1373+
}
1374+
13301375
pub fn verbose(&self) -> bool {
13311376
self.verbose > 0
13321377
}
@@ -1437,6 +1482,44 @@ fn download_ci_rustc_commit(download_rustc: Option<StringOrBool>, verbose: bool)
14371482
Some(commit.to_string())
14381483
}
14391484

1485+
fn maybe_download_rustfmt(builder: &Builder<'_>) -> Option<PathBuf> {
1486+
#[derive(Deserialize)]
1487+
struct Stage0Metadata {
1488+
dist_server: String,
1489+
rustfmt: Option<RustfmtMetadata>,
1490+
}
1491+
#[derive(Deserialize)]
1492+
struct RustfmtMetadata {
1493+
date: String,
1494+
version: String,
1495+
}
1496+
1497+
let stage0_json = builder.read(&builder.src.join("src").join("stage0.json"));
1498+
let metadata = t!(serde_json::from_str::<Stage0Metadata>(&stage0_json));
1499+
let RustfmtMetadata { date, version } = metadata.rustfmt?;
1500+
let channel = format!("{version}-{date}");
1501+
let mut dist_server = env::var("RUSTUP_DIST_SERVER").unwrap_or(metadata.dist_server);
1502+
dist_server.push_str("/dist");
1503+
1504+
let host = builder.config.build;
1505+
let rustfmt_path = builder.config.initial_rustc.with_file_name(exe("rustfmt", host));
1506+
let bin_root = builder.config.out.join(host.triple).join("stage0");
1507+
let rustfmt_stamp = bin_root.join(".rustfmt-stamp");
1508+
if rustfmt_path.exists() && !program_out_of_date(&rustfmt_stamp, &channel) {
1509+
return Some(rustfmt_path);
1510+
}
1511+
1512+
let filename = format!("rustfmt-{version}-{build}.tar.xz", build = host.triple);
1513+
download_component(builder, &dist_server, filename, "rustfmt-preview", &date, "stage0");
1514+
assert!(rustfmt_path.exists());
1515+
1516+
builder.fix_bin_or_dylib(&bin_root.join("bin").join("rustfmt"));
1517+
builder.fix_bin_or_dylib(&bin_root.join("bin").join("cargo-fmt"));
1518+
1519+
builder.create(&rustfmt_stamp, &channel);
1520+
Some(rustfmt_path)
1521+
}
1522+
14401523
fn download_ci_rustc(builder: &Builder<'_>, commit: &str) {
14411524
builder.verbose(&format!("using downloaded stage2 artifacts from CI (commit {commit})"));
14421525
// FIXME: support downloading artifacts from the beta channel
@@ -1474,18 +1557,34 @@ fn download_ci_rustc(builder: &Builder<'_>, commit: &str) {
14741557
/// Download a single component of a CI-built toolchain (not necessarily a published nightly).
14751558
// NOTE: intentionally takes an owned string to avoid downloading multiple times by accident
14761559
fn download_ci_component(builder: &Builder<'_>, filename: String, prefix: &str, commit: &str) {
1560+
download_component(
1561+
builder,
1562+
"https://ci-artifacts.rust-lang.org/rustc-builds",
1563+
filename,
1564+
prefix,
1565+
commit,
1566+
"ci-rustc",
1567+
)
1568+
}
1569+
1570+
fn download_component(
1571+
builder: &Builder<'_>,
1572+
base_url: &str,
1573+
filename: String,
1574+
prefix: &str,
1575+
key: &str,
1576+
destination: &str,
1577+
) {
14771578
let cache_dst = builder.out.join("cache");
1478-
let rustc_cache = cache_dst.join(commit);
1479-
if !rustc_cache.exists() {
1480-
t!(fs::create_dir_all(&rustc_cache));
1579+
let cache_dir = cache_dst.join(key);
1580+
if !cache_dir.exists() {
1581+
t!(fs::create_dir_all(&cache_dir));
14811582
}
14821583

1483-
let base = "https://ci-artifacts.rust-lang.org";
1484-
let url = format!("rustc-builds/{commit}");
1485-
let tarball = rustc_cache.join(&filename);
1584+
let tarball = cache_dir.join(&filename);
14861585
if !tarball.exists() {
1487-
builder.download_component(base, &format!("{url}/{filename}"), &tarball, "");
1586+
builder.download_component(base_url, &format!("{key}/{filename}"), &tarball, "");
14881587
}
1489-
let bin_root = builder.out.join(builder.config.build.triple).join("ci-rustc");
1588+
let bin_root = builder.out.join(builder.config.build.triple).join(destination);
14901589
builder.unpack(&tarball, &bin_root, prefix)
14911590
}

src/bootstrap/format.rs

+7-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Runs rustfmt on the repository.
22
3+
use crate::builder::Builder;
34
use crate::util::{output, t};
4-
use crate::Build;
55
use ignore::WalkBuilder;
66
use std::collections::VecDeque;
77
use std::path::{Path, PathBuf};
@@ -42,7 +42,7 @@ struct RustfmtConfig {
4242
ignore: Vec<String>,
4343
}
4444

45-
pub fn format(build: &Build, check: bool, paths: &[PathBuf]) {
45+
pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
4646
if build.config.dry_run {
4747
return;
4848
}
@@ -112,15 +112,11 @@ pub fn format(build: &Build, check: bool, paths: &[PathBuf]) {
112112
}
113113
let ignore_fmt = ignore_fmt.build().unwrap();
114114

115-
let rustfmt_path = build
116-
.config
117-
.initial_rustfmt
118-
.as_ref()
119-
.unwrap_or_else(|| {
120-
eprintln!("./x.py fmt is not supported on this channel");
121-
std::process::exit(1);
122-
})
123-
.to_path_buf();
115+
let rustfmt_path = build.initial_rustfmt().unwrap_or_else(|| {
116+
eprintln!("./x.py fmt is not supported on this channel");
117+
std::process::exit(1);
118+
});
119+
assert!(rustfmt_path.exists(), "{}", rustfmt_path.display());
124120
let src = build.src.clone();
125121
let (tx, rx): (SyncSender<PathBuf>, _) = std::sync::mpsc::sync_channel(128);
126122
let walker = match paths.get(0) {

src/bootstrap/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,7 @@ impl Build {
661661
self.maybe_update_submodules();
662662

663663
if let Subcommand::Format { check, paths } = &self.config.cmd {
664-
return format::format(self, *check, &paths);
664+
return format::format(&builder::Builder::new(&self), *check, &paths);
665665
}
666666

667667
if let Subcommand::Clean { all } = self.config.cmd {

0 commit comments

Comments
 (0)