]> git.proxmox.com Git - rustc.git/blame - src/tools/bump-stage0/src/main.rs
bump version to 1.80.1+dfsg1-1~bpo12+pve1
[rustc.git] / src / tools / bump-stage0 / src / main.rs
CommitLineData
31ef2f64
FG
1#![deny(unused_variables)]
2
9c376795 3use anyhow::{Context, Error};
31ef2f64 4use build_helper::stage0_parser::{parse_stage0_file, Stage0Config, VersionMetadata};
c295e0f8
XL
5use curl::easy::Easy;
6use indexmap::IndexMap;
7use std::collections::HashMap;
c295e0f8 8
31ef2f64 9const PATH: &str = "src/stage0";
4b012472 10const COMPILER_COMPONENTS: &[&str] = &["rustc", "rust-std", "cargo", "clippy-preview"];
9ffffee4 11const RUSTFMT_COMPONENTS: &[&str] = &["rustfmt-preview", "rustc"];
c295e0f8
XL
12
13struct Tool {
31ef2f64 14 config: Stage0Config,
923072b8 15
c295e0f8 16 channel: Channel,
9c376795 17 date: Option<String>,
c295e0f8
XL
18 version: [u16; 3],
19 checksums: IndexMap<String, String>,
20}
21
22impl Tool {
9c376795 23 fn new(date: Option<String>) -> Result<Self, Error> {
c295e0f8
XL
24 let channel = match std::fs::read_to_string("src/ci/channel")?.trim() {
25 "stable" => Channel::Stable,
26 "beta" => Channel::Beta,
27 "nightly" => Channel::Nightly,
28 other => anyhow::bail!("unsupported channel: {}", other),
29 };
30
31 // Split "1.42.0" into [1, 42, 0]
32 let version = std::fs::read_to_string("src/version")?
33 .trim()
34 .split('.')
35 .map(|val| val.parse())
36 .collect::<Result<Vec<_>, _>>()?
37 .try_into()
38 .map_err(|_| anyhow::anyhow!("failed to parse version"))?;
39
31ef2f64 40 let existing = parse_stage0_file();
923072b8 41
31ef2f64 42 Ok(Self { channel, version, date, config: existing.config, checksums: IndexMap::new() })
c295e0f8
XL
43 }
44
31ef2f64
FG
45 fn update_stage0_file(mut self) -> Result<(), Error> {
46 const COMMENTS: &str = r#"# The configuration above this comment is editable, and can be changed
47# by forks of the repository if they have alternate values.
48#
49# The section below is generated by `./x.py run src/tools/bump-stage0`,
50# run that command again to update the bootstrap compiler.
51#
52# All changes below this comment will be overridden the next time the
53# tool is executed.
54 "#;
55
56 let mut file_content = String::new();
57
58 // Destructure `Stage0Config` here to ensure the stage0 file is synced with any new
59 // fields when they are added.
60 let Stage0Config {
61 dist_server,
62 artifacts_server,
63 artifacts_with_llvm_assertions_server,
64 git_merge_commit_email,
65 git_repository,
66 nightly_branch,
67 } = &self.config;
68
69 file_content.push_str(&format!("dist_server={}", dist_server));
70 file_content.push_str(&format!("\nartifacts_server={}", artifacts_server));
71 file_content.push_str(&format!(
72 "\nartifacts_with_llvm_assertions_server={}",
73 artifacts_with_llvm_assertions_server
74 ));
75 file_content.push_str(&format!("\ngit_merge_commit_email={}", git_merge_commit_email));
76 file_content.push_str(&format!("\ngit_repository={}", git_repository));
77 file_content.push_str(&format!("\nnightly_branch={}", nightly_branch));
78
79 file_content.push_str("\n\n");
80 file_content.push_str(COMMENTS);
81
82 let compiler = self.detect_compiler()?;
83 file_content.push_str(&format!("\ncompiler_date={}", compiler.date));
84 file_content.push_str(&format!("\ncompiler_version={}", compiler.version));
85
86 if let Some(rustfmt) = self.detect_rustfmt()? {
87 file_content.push_str(&format!("\nrustfmt_date={}", rustfmt.date));
88 file_content.push_str(&format!("\nrustfmt_version={}", rustfmt.version));
89 }
90
91 file_content.push_str("\n");
92
93 for (key, value) in self.checksums {
94 file_content.push_str(&format!("\n{}={}", key, value));
95 }
96
97 std::fs::write(PATH, file_content)?;
c295e0f8
XL
98 Ok(())
99 }
100
101 // Currently Rust always bootstraps from the previous stable release, and in our train model
102 // this means that the master branch bootstraps from beta, beta bootstraps from current stable,
103 // and stable bootstraps from the previous stable release.
104 //
105 // On the master branch the compiler version is configured to `beta` whereas if you're looking
106 // at the beta or stable channel you'll likely see `1.x.0` as the version, with the previous
107 // release's version number.
31ef2f64 108 fn detect_compiler(&mut self) -> Result<VersionMetadata, Error> {
c295e0f8
XL
109 let channel = match self.channel {
110 Channel::Stable | Channel::Beta => {
111 // The 1.XX manifest points to the latest point release of that minor release.
112 format!("{}.{}", self.version[0], self.version[1] - 1)
113 }
114 Channel::Nightly => "beta".to_string(),
115 };
116
9c376795 117 let manifest = fetch_manifest(&self.config, &channel, self.date.as_deref())?;
c295e0f8 118 self.collect_checksums(&manifest, COMPILER_COMPONENTS)?;
31ef2f64 119 Ok(VersionMetadata {
c295e0f8
XL
120 date: manifest.date,
121 version: if self.channel == Channel::Nightly {
122 "beta".to_string()
123 } else {
124 // The version field is like "1.42.0 (abcdef1234 1970-01-01)"
125 manifest.pkg["rust"]
126 .version
127 .split_once(' ')
128 .expect("invalid version field")
129 .0
130 .to_string()
131 },
132 })
133 }
134
135 /// We use a nightly rustfmt to format the source because it solves some bootstrapping issues
136 /// with use of new syntax in this repo. For the beta/stable channels rustfmt is not provided,
137 /// as we don't want to depend on rustfmt from nightly there.
31ef2f64 138 fn detect_rustfmt(&mut self) -> Result<Option<VersionMetadata>, Error> {
c295e0f8
XL
139 if self.channel != Channel::Nightly {
140 return Ok(None);
141 }
142
9c376795 143 let manifest = fetch_manifest(&self.config, "nightly", self.date.as_deref())?;
c295e0f8 144 self.collect_checksums(&manifest, RUSTFMT_COMPONENTS)?;
31ef2f64 145 Ok(Some(VersionMetadata { date: manifest.date, version: "nightly".into() }))
c295e0f8
XL
146 }
147
148 fn collect_checksums(&mut self, manifest: &Manifest, components: &[&str]) -> Result<(), Error> {
923072b8 149 let prefix = format!("{}/", self.config.dist_server);
c295e0f8
XL
150 for component in components {
151 let pkg = manifest
152 .pkg
153 .get(*component)
154 .ok_or_else(|| anyhow::anyhow!("missing component from manifest: {}", component))?;
155 for target in pkg.target.values() {
156 for pair in &[(&target.url, &target.hash), (&target.xz_url, &target.xz_hash)] {
157 if let (Some(url), Some(sha256)) = pair {
158 let url = url
159 .strip_prefix(&prefix)
160 .ok_or_else(|| {
161 anyhow::anyhow!("url doesn't start with dist server base: {}", url)
162 })?
163 .to_string();
164 self.checksums.insert(url, sha256.clone());
165 }
166 }
167 }
168 }
169 Ok(())
170 }
171}
172
173fn main() -> Result<(), Error> {
9c376795 174 let tool = Tool::new(std::env::args().nth(1))?;
31ef2f64 175 tool.update_stage0_file()?;
c295e0f8
XL
176 Ok(())
177}
178
31ef2f64
FG
179fn fetch_manifest(
180 config: &Stage0Config,
181 channel: &str,
182 date: Option<&str>,
183) -> Result<Manifest, Error> {
9c376795
FG
184 let url = if let Some(date) = date {
185 format!("{}/dist/{}/channel-rust-{}.toml", config.dist_server, date, channel)
186 } else {
187 format!("{}/dist/channel-rust-{}.toml", config.dist_server, channel)
188 };
189
190 Ok(toml::from_slice(&http_get(&url)?)?)
c295e0f8
XL
191}
192
193fn http_get(url: &str) -> Result<Vec<u8>, Error> {
194 let mut data = Vec::new();
195 let mut handle = Easy::new();
196 handle.fail_on_error(true)?;
197 handle.url(url)?;
198 {
199 let mut transfer = handle.transfer();
200 transfer.write_function(|new_data| {
201 data.extend_from_slice(new_data);
202 Ok(new_data.len())
203 })?;
9c376795 204 transfer.perform().context(format!("failed to fetch {url}"))?;
c295e0f8
XL
205 }
206 Ok(data)
207}
208
209#[derive(Debug, PartialEq, Eq)]
210enum Channel {
211 Stable,
212 Beta,
213 Nightly,
214}
215
923072b8 216#[derive(Debug, serde::Serialize, serde::Deserialize)]
c295e0f8
XL
217struct Manifest {
218 date: String,
219 pkg: HashMap<String, ManifestPackage>,
220}
221
923072b8 222#[derive(Debug, serde::Serialize, serde::Deserialize)]
c295e0f8
XL
223struct ManifestPackage {
224 version: String,
225 target: HashMap<String, ManifestTargetPackage>,
226}
227
923072b8 228#[derive(Debug, serde::Serialize, serde::Deserialize)]
c295e0f8 229struct ManifestTargetPackage {
c295e0f8
XL
230 url: Option<String>,
231 hash: Option<String>,
232 xz_url: Option<String>,
233 xz_hash: Option<String>,
234}