diff --git a/Cargo.lock b/Cargo.lock index 779f2c2..a7f2fcb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -161,6 +161,9 @@ name = "cc" version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66120af515773fb005778dc07c261bd201ec8ce50bd6e7144c927753fe013381" +dependencies = [ + "jobserver", +] [[package]] name = "cfb-mode" @@ -501,6 +504,21 @@ dependencies = [ "wasi 0.9.0+wasi-snapshot-preview1", ] +[[package]] +name = "git2" +version = "0.13.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e094214efbc7fdbbdee952147e493b00e99a4e52817492277e98967ae918165" +dependencies = [ + "bitflags", + "libc", + "libgit2-sys", + "log", + "openssl-probe", + "openssl-sys", + "url", +] + [[package]] name = "hermit-abi" version = "0.1.15" @@ -522,12 +540,32 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "idna" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "itoa" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" +[[package]] +name = "jobserver" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" +dependencies = [ + "libc", +] + [[package]] name = "keccak" version = "0.1.0" @@ -549,12 +587,40 @@ version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" +[[package]] +name = "libgit2-sys" +version = "0.12.13+1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069eea34f76ec15f2822ccf78fe0cdb8c9016764d0a12865278585a74dbdeae5" +dependencies = [ + "cc", + "libc", + "libssh2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", +] + [[package]] name = "libm" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" +[[package]] +name = "libssh2-sys" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca46220853ba1c512fc82826d0834d87b06bcd3c2a42241b7de72f3d2fe17056" +dependencies = [ + "cc", + "libc", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", +] + [[package]] name = "libz-sys" version = "1.1.2" @@ -587,6 +653,12 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "matches" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" + [[package]] name = "maybe-uninit" version = "2.0.0" @@ -761,6 +833,12 @@ dependencies = [ "regex", ] +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + [[package]] name = "pgp" version = "0.7.1" @@ -840,6 +918,7 @@ dependencies = [ "curl", "flate2", "fs2", + "git2", "hex", "pgp", "rand 0.6.5", @@ -848,6 +927,7 @@ dependencies = [ "serde_json", "sha2", "tar", + "tempfile", "toml", "xz2", ] @@ -1066,6 +1146,15 @@ version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + [[package]] name = "ripemd160" version = "0.9.1" @@ -1294,6 +1383,20 @@ dependencies = [ "xattr", ] +[[package]] +name = "tempfile" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +dependencies = [ + "cfg-if", + "libc", + "rand 0.7.3", + "redox_syscall", + "remove_dir_all", + "winapi", +] + [[package]] name = "thiserror" version = "1.0.21" @@ -1334,6 +1437,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "tinyvec" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117" + [[package]] name = "toml" version = "0.4.10" @@ -1369,12 +1478,41 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +dependencies = [ + "matches", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-xid" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +[[package]] +name = "url" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" +dependencies = [ + "idna", + "matches", + "percent-encoding", +] + [[package]] name = "vcpkg" version = "0.2.10" diff --git a/Cargo.toml b/Cargo.toml index 4482d28..2e6c758 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,8 @@ authors = ["Alex Crichton "] license = "MIT OR Apache-2.0" edition = "2018" +build = "build.rs" + [dependencies] curl = "0.4" flate2 = "1" @@ -21,3 +23,5 @@ sha2 = "0.9.1" hex = "0.4.2" pgp = "0.7.1" chrono = "0.4.19" +git2 = "0.13.11" +tempfile = "3.1.0" diff --git a/README.md b/README.md index 82a6e6a..2b24806 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,13 @@ environment variable while calling `rustup`: RUSTUP_DIST_SERVER="http://localhost:9000/static" ``` +You can also release a specific commit by providing its full hash as the second +argument of `./run.sh`: + +``` +./run.sh nightly 0000000000000000000000000000000000000000 +``` + ### Adding additional files to the local release To save on time and bandwidth, when running a release locally the tooling won't diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..b6a4c80 --- /dev/null +++ b/build.rs @@ -0,0 +1,10 @@ +fn main() { + // Prevent a rebuild every time a non-Rust file is changed. + println!("cargo:rerun-if-changed=build.rs"); + + // Provide the current target as environment variable. + println!( + "cargo:rustc-env=TARGET={}", + std::env::var("TARGET").unwrap() + ); +} diff --git a/local/run.sh b/local/run.sh index 6eb8705..d515ee1 100755 --- a/local/run.sh +++ b/local/run.sh @@ -13,6 +13,7 @@ RUSTC_DEFAULT_BRANCH="master" DOWNLOAD_BASE="https://ci-artifacts.rust-lang.org/rustc-builds" # Rustup components to download for each target we want to release. DOWNLOAD_COMPONENTS=( + "build-manifest" "cargo" "rust" "rust-docs" @@ -35,6 +36,7 @@ DOWNLOAD_STANDALONE=( ) channel="$1" +override_commit="$2" # Nightly is on the default branch if [[ "${channel}" = "nightly" ]]; then @@ -46,8 +48,13 @@ fi echo "==> overriding files to force promote-release to run" mc cp "/src/local/channel-rust-${channel}.toml" "local/static/dist/channel-rust-${channel}.toml" >/dev/null -echo "==> detecting the last rustc commit on branch ${branch}" -commit="$(git ls-remote "${RUSTC_REPO}" | grep "refs/heads/${branch}" | awk '{print($1)}')" +if [[ "${override_commit}" = "" ]]; then + echo "==> detecting the last rustc commit on branch ${branch}" + commit="$(git ls-remote "${RUSTC_REPO}" | grep "refs/heads/${branch}" | awk '{print($1)}')" +else + echo "=>> using overridden commit ${override_commit}" + commit="${override_commit}" +fi # While the nightly and beta channels have the channel name as the "release" in # the archive names, the stable channel uses the actual Rust and Cargo version @@ -86,8 +93,9 @@ download() { file="$1" if ! mc stat "local/artifacts/builds/${commit}/${file}" >/dev/null 2>&1; then echo "==> copying ${file} from ci-artifacts.rust-lang.org" - curl -Lo /tmp/component "${DOWNLOAD_BASE}/${commit}/${file}" --fail - mc cp /tmp/component "local/artifacts/builds/${commit}/${file}" >/dev/null + if curl -Lo /tmp/component "${DOWNLOAD_BASE}/${commit}/${file}" --fail; then + mc cp /tmp/component "local/artifacts/builds/${commit}/${file}" >/dev/null + fi else echo "==> reusing cached ${file}" fi @@ -129,6 +137,10 @@ export PROMOTE_RELEASE_GZIP_COMPRESSION_LEVEL="1" # Faster recompressions export PROMOTE_RELEASE_S3_ENDPOINT_URL="http://minio:9000" export PROMOTE_RELEASE_SKIP_CLOUDFRONT_INVALIDATIONS="yes" export PROMOTE_RELEASE_SKIP_DELETE_BUILD_DIR="yes" +# Conditional environment variables +if [[ "${override_commit}" != "" ]]; then + export PROMOTE_RELEASE_OVERRIDE_COMMIT="${override_commit}" +fi echo "==> starting promote-release" /src/target/release/promote-release /persistent/release "${channel}" diff --git a/prod/Dockerfile b/prod/Dockerfile index da4188e..a8c468a 100644 --- a/prod/Dockerfile +++ b/prod/Dockerfile @@ -22,7 +22,7 @@ ENV PATH=/root/.cargo/bin:$PATH # caching, and it works by copying the Cargo.{toml,lock} with dummy source code # and doing a full build with it. WORKDIR /tmp/source -COPY Cargo.lock Cargo.toml /tmp/source/ +COPY Cargo.lock Cargo.toml build.rs /tmp/source/ RUN mkdir -p /tmp/source/src && \ echo "fn main() {}" > /tmp/source/src/main.rs RUN cargo fetch diff --git a/run.sh b/run.sh index b2d67be..e2a66c0 100755 --- a/run.sh +++ b/run.sh @@ -5,11 +5,12 @@ set -euo pipefail IFS=$'\n\t' -if [[ "$#" -ne 1 ]]; then - echo "Usage: $0 " +if [[ "$#" -lt 1 ]] || [[ "$#" -gt 2 ]]; then + echo "Usage: $0 [commit]" exit 1 fi channel="$1" +override_commit="${2-}" container_id="$(docker-compose ps -q local)" if [[ "${container_id}" == "" ]]; then @@ -30,4 +31,4 @@ fi cargo build --release # Run the command inside the docker environment. -docker-compose exec -T local /src/local/run.sh "${channel}" +docker-compose exec -T local /src/local/run.sh "${channel}" "${override_commit}" diff --git a/src/build_manifest.rs b/src/build_manifest.rs new file mode 100644 index 0000000..8776071 --- /dev/null +++ b/src/build_manifest.rs @@ -0,0 +1,84 @@ +use crate::{config::Channel, Context}; +use anyhow::{Context as _, Error}; +use std::{ + fs::File, + io::BufReader, + path::{Path, PathBuf}, + process::Command, +}; +use tar::Archive; +use tempfile::NamedTempFile; +use xz2::read::XzDecoder; + +pub(crate) struct BuildManifest<'a> { + builder: &'a Context, + tarball_name: String, + tarball_path: PathBuf, +} + +impl<'a> BuildManifest<'a> { + pub(crate) fn new(builder: &'a Context) -> Self { + // Precalculate paths used later. + let release = match builder.config.channel { + Channel::Stable => builder.current_version.clone().unwrap(), + channel => channel.to_string(), + }; + let tarball_name = format!("build-manifest-{}-{}", release, crate::TARGET); + let tarball_path = builder.dl_dir().join(format!("{}.tar.xz", tarball_name)); + + Self { + builder, + tarball_name, + tarball_path, + } + } + + pub(crate) fn exists(&self) -> bool { + self.tarball_path.is_file() + } + + pub(crate) fn run(&self) -> Result<(), Error> { + let config = &self.builder.config; + let bin = self + .extract() + .context("failed to extract build-manifest from the tarball")?; + + println!("running build-manifest..."); + let upload_addr = format!("{}/{}", config.upload_addr, config.upload_dir); + // build-manifest + let status = Command::new(bin.path()) + .arg(self.builder.dl_dir()) + .arg(self.builder.dl_dir()) + .arg(&self.builder.date) + .arg(upload_addr) + .arg(config.channel.to_string()) + .status() + .context("failed to execute build-manifest")?; + + if status.success() { + Ok(()) + } else { + anyhow::bail!("build-manifest failed with status {:?}", status); + } + } + + fn extract(&self) -> Result { + let binary_path = Path::new(&self.tarball_name) + .join("build-manifest") + .join("bin") + .join("build-manifest"); + + let tarball_file = BufReader::new(File::open(&self.tarball_path)?); + let mut tarball = Archive::new(XzDecoder::new(tarball_file)); + + let bin = NamedTempFile::new()?; + tarball + .entries()? + .filter_map(|e| e.ok()) + .find(|e| e.path().ok().as_deref() == Some(&binary_path)) + .ok_or_else(|| anyhow::anyhow!("missing build-manifest binary inside the tarball"))? + .unpack(bin.path())?; + + Ok(bin) + } +} diff --git a/src/config.rs b/src/config.rs index be0cc46..cc873be 100644 --- a/src/config.rs +++ b/src/config.rs @@ -4,9 +4,39 @@ use std::str::FromStr; const ENVIRONMENT_VARIABLE_PREFIX: &str = "PROMOTE_RELEASE_"; +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub(crate) enum Channel { + Stable, + Beta, + Nightly, +} + +impl FromStr for Channel { + type Err = Error; + + fn from_str(input: &str) -> Result { + match input { + "stable" => Ok(Channel::Stable), + "beta" => Ok(Channel::Beta), + "nightly" => Ok(Channel::Nightly), + _ => anyhow::bail!("unknown channel: {}", input), + } + } +} + +impl std::fmt::Display for Channel { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + Channel::Stable => "stable", + Channel::Beta => "beta", + Channel::Nightly => "nightly", + }) + } +} + pub(crate) struct Config { /// The channel we're currently releasing. - pub(crate) channel: String, + pub(crate) channel: Channel, /// CloudFront distribution ID for doc.rust-lang.org. pub(crate) cloudfront_doc_id: String, /// CloudFront distribution ID for static.rust-lang.org. @@ -19,6 +49,8 @@ pub(crate) struct Config { pub(crate) gpg_key_file: String, /// Path of the file containing the password of the GPG secret key. pub(crate) gpg_password_file: String, + /// URL of the git repository containing the Rust source code. + pub(crate) repository: String, /// Remote HTTP host artifacts will be uploaded to. Note that this is *not* the same as what's /// configured in `config.toml` for rustbuild, it's just the *host* that we're uploading to and /// going to be looking at urls from. @@ -40,8 +72,8 @@ pub(crate) struct Config { /// The compression level to use when recompressing tarballs with gzip. pub(crate) gzip_compression_level: u32, - /// Custom name of the branch to start the release process from, instead of the default one. - pub(crate) override_branch: Option, + /// Custom sha of the commit to release, instead of the latest commit in the channel's branch. + pub(crate) override_commit: Option, /// Custom Endpoint URL for S3. Set this if you want to point to an S3-compatible service /// instead of the AWS one. pub(crate) s3_endpoint_url: Option, @@ -65,7 +97,8 @@ impl Config { gpg_key_file: require_env("GPG_KEY_FILE")?, gpg_password_file: require_env("GPG_PASSWORD_FILE")?, gzip_compression_level: default_env("GZIP_COMPRESSION_LEVEL", 9)?, - override_branch: maybe_env("OVERRIDE_BRANCH")?, + override_commit: maybe_env("OVERRIDE_COMMIT")?, + repository: default_env("REPOSITORY", "https://github.com/rust-lang/rust.git".into())?, s3_endpoint_url: maybe_env("S3_ENDPOINT_URL")?, skip_cloudfront_invalidations: bool_env("SKIP_CLOUDFRONT_INVALIDATIONS")?, skip_delete_build_dir: bool_env("SKIP_DELETE_BUILD_DIR")?, diff --git a/src/main.rs b/src/main.rs index 77af4c3..5ed320e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +mod build_manifest; mod config; mod sign; @@ -9,12 +10,17 @@ use std::process::Command; use std::time::Instant; use anyhow::Error; +use build_manifest::BuildManifest; +use chrono::Utc; use curl::easy::Easy; use fs2::FileExt; use rayon::prelude::*; use sign::Signer; +use xz2::read::XzDecoder; -use crate::config::Config; +use crate::config::{Channel, Config}; + +const TARGET: &str = env!("TARGET"); struct Context { work: PathBuf, @@ -28,35 +34,29 @@ struct Context { // // $prog work/dir fn main() -> Result<(), Error> { - Context { - work: env::current_dir()?.join(env::args_os().nth(1).unwrap()), - config: Config::from_env()?, - handle: Easy::new(), - date: output(Command::new("date").arg("+%Y-%m-%d"))? - .trim() - .to_string(), - current_version: None, - } - .run() + let mut context = Context::new( + env::current_dir()?.join(env::args_os().nth(1).unwrap()), + Config::from_env()?, + )?; + context.run() } impl Context { + fn new(work: PathBuf, config: Config) -> Result { + let date = Utc::now().format("%Y-%m-%d").to_string(); + + Ok(Context { + work, + config, + date, + handle: Easy::new(), + current_version: None, + }) + } + fn run(&mut self) -> Result<(), Error> { let _lock = self.lock()?; - self.update_repo()?; - - let branch = if let Some(branch) = self.config.override_branch.clone() { - branch - } else { - match &self.config.channel[..] { - "nightly" => "master", - "beta" => "beta", - "stable" => "stable", - _ => panic!("unknown release: {}", self.config.channel), - } - .to_string() - }; - self.do_release(&branch)?; + self.do_release()?; Ok(()) } @@ -77,7 +77,7 @@ impl Context { /// Update the rust repository we have cached, either cloning a fresh one or /// fetching remote references - fn update_repo(&mut self) -> Result<(), Error> { + fn legacy_update_repo(&mut self) -> Result<(), Error> { // Clone/update the repo let dir = self.rust_dir(); if dir.is_dir() { @@ -97,17 +97,36 @@ impl Context { Ok(()) } - /// Does a release for the `branch` specified. - fn do_release(&mut self, branch: &str) -> Result<(), Error> { - // Learn the precise rev of the remote branch, this'll guide what we - // download. - let rev = output( - Command::new("git") - .arg("rev-parse") - .arg(format!("origin/{}", branch)) - .current_dir(&self.rust_dir()), - )?; - let rev = rev.trim(); + fn get_commit_sha(&self) -> Result { + if let Some(commit) = self.config.override_commit.clone() { + return Ok(commit); + } + + let git_ref = match self.config.channel { + Channel::Nightly => "refs/heads/master", + Channel::Beta => "refs/heads/beta", + Channel::Stable => "refs/heads/stable", + }; + + // git2 requires a git repository to be able to connect to a remote and fetch metadata, so + // this creates an empty repository in a temporary directory. It will be deleted once the + // function returns. + let temp = tempfile::tempdir()?; + let repo = git2::Repository::init(temp.path())?; + + let mut remote = repo.remote("origin", &self.config.repository)?; + remote.connect(git2::Direction::Fetch)?; + + for head in remote.list()? { + if head.name() == git_ref { + return Ok(hex::encode(head.oid().as_bytes())); + } + } + anyhow::bail!("missing git ref in {}: {}", self.config.repository, git_ref); + } + + fn do_release(&mut self) -> Result<(), Error> { + let rev = self.get_commit_sha()?; println!("{} rev is {}", self.config.channel, rev); // Download the current live manifest for the channel we're releasing. @@ -153,34 +172,23 @@ impl Context { self.assert_all_components_present()?; - // Ok we've now determined that a release needs to be done. Let's - // configure rust, build a manifest and sign the artifacts we just downloaded, and upload the - // signatures and manifest to the CI bucket. - - self.configure_rust(rev)?; - - let is_legacy_build_manifest = !self - .rust_dir() - .join("src/tools/build-manifest/src/manifest.rs") - .exists(); - println!("is legacy build-manifest: {}", is_legacy_build_manifest); + // Ok we've now determined that a release needs to be done. - if is_legacy_build_manifest { - self.sign_artifacts()?; - } else { - self.build_manifest()?; - } + let build_manifest = BuildManifest::new(self); + if build_manifest.exists() { + // Generate the channel manifest + build_manifest.run()?; - // Merge all the signatures with the download files, and then sync that - // whole dir up to the release archives - for file in self.build_dir().join("build/dist/").read_dir()? { - let file = file?; - fs::copy(file.path(), self.dl_dir().join(file.file_name()))?; - } - - if !is_legacy_build_manifest { + // Generate checksums and sign all the files we're about to ship. let signer = Signer::new(&self.config)?; signer.sign_directory(&self.dl_dir())?; + } else { + // For releases using the legacy build-manifest, we need to clone the rustc monorepo + // and invoke `./x.py dist hash-and-sign` in it. This won't be needed after 1.48.0 is + // out in the stable channel. + self.legacy_update_repo()?; + self.legacy_configure_rust(&rev)?; + self.legacy_sign_artifacts()?; } self.publish_archive()?; @@ -196,7 +204,7 @@ impl Context { Ok(()) } - fn configure_rust(&mut self, rev: &str) -> Result<(), Error> { + fn legacy_configure_rust(&mut self, rev: &str) -> Result<(), Error> { let build = self.build_dir(); // Only delete the dist artifacts when running the tool locally, to avoid rebuilding // bootstrap over and over again. @@ -247,7 +255,7 @@ upload-addr = \"{}/{}\" fn current_version_same(&mut self, prev: &str) -> Result { // nightly's always changing - if self.config.channel == "nightly" { + if self.config.channel == Channel::Nightly { return Ok(false); } let prev_version = prev.split(' ').next().unwrap(); @@ -318,7 +326,7 @@ upload-addr = \"{}/{}\" /// Note that we already don't merge PRs in rust-lang/rust that don't /// build cargo, so this cannot realistically fail. fn assert_all_components_present(&self) -> Result<(), Error> { - if self.config.channel != "nightly" { + if self.config.channel != Channel::Nightly { return Ok(()); } @@ -413,7 +421,7 @@ upload-addr = \"{}/{}\" println!("recompressing {}...", gz_path.display()); let xz = File::open(xz_path)?; - let mut xz = xz2::read::XzDecoder::new(xz); + let mut xz = XzDecoder::new(xz); let gz = File::create(gz_path)?; let mut gz = flate2::write::GzEncoder::new(gz, compression_level); io::copy(&mut xz, &mut gz)?; @@ -433,20 +441,22 @@ upload-addr = \"{}/{}\" } /// Create manifest and sign the artifacts. - fn sign_artifacts(&mut self) -> Result<(), Error> { + fn legacy_sign_artifacts(&mut self) -> Result<(), Error> { let build = self.build_dir(); // This calls `src/tools/build-manifest` from the rustc repo. run(Command::new(self.rust_dir().join("x.py")) .current_dir(&build) .arg("dist") - .arg("hash-and-sign")) - } + .arg("hash-and-sign"))?; - fn build_manifest(&mut self) -> Result<(), Error> { - run(Command::new(self.rust_dir().join("x.py")) - .current_dir(&self.build_dir()) - .arg("run") - .arg("src/tools/build-manifest")) + // Merge all the signatures with the download files, and then sync that + // whole dir up to the release archives + for file in self.build_dir().join("build/dist/").read_dir()? { + let file = file?; + fs::copy(file.path(), self.dl_dir().join(file.file_name()))?; + } + + Ok(()) } fn publish_archive(&mut self) -> Result<(), Error> { @@ -467,14 +477,13 @@ upload-addr = \"{}/{}\" } fn publish_docs(&mut self) -> Result<(), Error> { - let (version, upload_dir) = match &self.config.channel[..] { - "stable" => { + let (version, upload_dir) = match self.config.channel { + Channel::Stable => { let vers = &self.current_version.as_ref().unwrap()[..]; (vers, "stable") } - "beta" => ("beta", "beta"), - "nightly" => ("nightly", "nightly"), - _ => panic!(), + Channel::Beta => ("beta", "beta"), + Channel::Nightly => ("nightly", "nightly"), }; // Pull out HTML documentation from one of the `rust-docs-*` tarballs. @@ -708,19 +717,3 @@ fn run(cmd: &mut Command) -> Result<(), Error> { } Ok(()) } - -fn output(cmd: &mut Command) -> Result { - println!("running {:?}", cmd); - let output = cmd.output()?; - if !output.status.success() { - anyhow::bail!( - "failed command:{:?}\n:{}\n\n{}\n\n{}", - cmd, - output.status, - String::from_utf8_lossy(&output.stdout), - String::from_utf8_lossy(&output.stderr), - ); - } - - Ok(String::from_utf8(output.stdout)?) -}