Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Give gnrt two subcommands (gen, download) and implement download
The download command pulls a crate from crates.io via `curl`, verifies the license is allowed, untars it into third_party/rust/ and writes a README.chromium file for it. R=collinbaker@chromium.org Bug: 1291994 Change-Id: I64ef8b23420826c8aea1089bb8b85daf1cdbe1c3 Cq-Include-Trybots: luci.chromium.try:android-rust-arm-dbg,android-rust-arm-rel,linux-rust-x64-dbg,linux-rust-x64-rel Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3913769 Reviewed-by: Collin Baker <collinbaker@chromium.org> Reviewed-by: Collin Baker <collinbaker@google.com> Commit-Queue: danakj <danakj@chromium.org> Cr-Commit-Position: refs/heads/main@{#1053245}
- Loading branch information
Showing
6 changed files
with
182 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
// Copyright 2022 The Chromium Authors | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
use std::io::{Read, Write}; | ||
use std::process::{self, ExitCode}; | ||
|
||
use crate::crates; | ||
use crate::manifest::CargoManifest; | ||
use crate::paths; | ||
|
||
/// Runs the download subcommand, which downloads a crate from crates.io and unpacks it into the | ||
/// Chromium tree. | ||
pub fn download( | ||
name: &str, | ||
version: semver::Version, | ||
security: bool, | ||
paths: &paths::ChromiumPaths, | ||
) -> ExitCode { | ||
let vendored_crate = crates::ChromiumVendoredCrate { | ||
name: name.to_string(), | ||
epoch: crates::Epoch::from_version(&version), | ||
}; | ||
let build_path = paths.third_party.join(vendored_crate.build_path()); | ||
let crate_path = paths.third_party.join(vendored_crate.crate_path()); | ||
|
||
let url = format!( | ||
"{dir}/{name}/{name}-{version}.{suffix}", | ||
dir = CRATES_IO_DOWNLOAD_URL, | ||
suffix = CRATES_IO_DOWNLOAD_SUFFIX | ||
); | ||
let curl_out = process::Command::new("curl") | ||
.arg("--fail") | ||
.arg(url.to_string()) | ||
.output() | ||
.expect("Failed to run curl"); | ||
if !curl_out.status.success() { | ||
eprintln!("gnrt: {}", String::from_utf8(curl_out.stderr).unwrap()); | ||
return ExitCode::FAILURE; | ||
} | ||
|
||
// Makes the directory where the build file will go. The crate's source code will go below it. | ||
// This directory and its parents are allowed to exist already. | ||
std::fs::create_dir_all(&build_path) | ||
.expect("Could not make the third-party directory '{build_path}' for the crate"); | ||
// Makes the directory where the source code will be unzipped. It should not exist or we'd be | ||
// clobbering existing files. | ||
std::fs::create_dir(&crate_path).expect("Crate directory '{crate_path}' already exists"); | ||
|
||
let mut untar = process::Command::new("tar") | ||
// Extract and unzip from stdin. | ||
.arg("xzf") | ||
.arg("-") | ||
// Drop the first path component, which is the crate's name-version. | ||
.arg("--strip-components=1") | ||
// Unzip into the crate's directory in third_party/rust. | ||
.arg(format!("--directory={}", crate_path.display())) | ||
// The input is the downloaded file. | ||
.stdin(process::Stdio::piped()) | ||
.stdout(process::Stdio::piped()) | ||
.stderr(process::Stdio::piped()) | ||
.spawn() | ||
.expect("Failed to run tar"); | ||
|
||
if untar.stdin.take().unwrap().write_all(&curl_out.stdout).is_err() { | ||
eprintln!("gnrt: Failed to pipe input to tar, it exited early"); | ||
} | ||
|
||
if !untar.wait().expect("Failed to wait for tar").success() { | ||
let mut stderr_buf = Vec::new(); | ||
untar.stderr.unwrap().read_to_end(&mut stderr_buf).expect("Failed to read stderr from tar"); | ||
eprintln!("gnrt: {}", String::from_utf8(stderr_buf).unwrap()); | ||
return ExitCode::FAILURE; | ||
} | ||
|
||
let cargo: CargoManifest = { | ||
let str = std::fs::read_to_string(crate_path.join("Cargo.toml")) | ||
.expect("Unable to open downloaded Cargo.toml"); | ||
toml::de::from_str(&str).expect("Unable to parse downloaded Cargo.toml") | ||
}; | ||
|
||
let (_, readme_license) = ALLOWED_LICENSES | ||
.iter() | ||
.find(|(allowed_license, _)| &cargo.package.license == *allowed_license) | ||
.expect("License in downloaded Cargo.toml is not in ALLOWED_LICENSES"); | ||
|
||
let readme = gen_readme_chromium_text(&cargo, readme_license, security); | ||
std::fs::write(build_path.join("README.chromium"), readme) | ||
.expect("Failed to write README.chromium"); | ||
|
||
println!("gnrt: Downloaded {name} {version} to {path}", path = crate_path.display()); | ||
|
||
ExitCode::SUCCESS | ||
} | ||
|
||
/// Generate the contents of the README.chromium file. | ||
fn gen_readme_chromium_text(manifest: &CargoManifest, license: &str, security: bool) -> String { | ||
format!( | ||
"Name: {crate_name}\n\ | ||
URL: {url}\n\ | ||
Description: {description}\n\ | ||
Version: {version}\n\ | ||
Security Critical: {security}\n\ | ||
License: {license}\n", | ||
crate_name = manifest.package.name, | ||
url = format!("{}/{}", CRATES_IO_VIEW_URL, manifest.package.name), | ||
description = manifest.package.description.as_ref().unwrap_or(&"".to_string()), | ||
version = manifest.package.version, | ||
) | ||
} | ||
|
||
static CRATES_IO_DOWNLOAD_URL: &str = "https://static.crates.io/crates"; | ||
static CRATES_IO_DOWNLOAD_SUFFIX: &str = "crate"; | ||
static CRATES_IO_VIEW_URL: &str = "https://crates.io/crates"; | ||
|
||
// Allowed licenses, in the format they are specified in Cargo.toml files from | ||
// crates.io, and the format to write to README.chromium. | ||
static ALLOWED_LICENSES: [(&str, &str); 15] = [ | ||
// ("Cargo.toml string", "License for README.chromium") | ||
("Apache-2.0", "Apache 2.0"), | ||
("MIT OR Apache-2.0", "Apache 2.0"), | ||
("MIT/Apache-2.0", "Apache 2.0"), | ||
("Apache-2.0 / MIT", "Apache 2.0"), | ||
("Apache-2.0 OR MIT", "Apache 2.0"), | ||
("Apache-2.0/MIT", "Apache 2.0"), | ||
("MIT", "MIT"), | ||
("Unlicense OR MIT", "MIT"), | ||
("Unlicense/MIT", "MIT"), | ||
("Apache-2.0 OR BSL-1.0", "Apache 2.0"), | ||
("BSD-3-Clause", "BSD 3-Clause"), | ||
("ISC", "ISC"), | ||
("MIT OR Zlib OR Apache-2.0", "Apache 2.0"), | ||
("0BSD OR MIT OR Apache-2.0", "Apache 2.0"), | ||
("Unicode-DFS-2016", "Unicode License Agreement - Data Files and Software (2016)"), | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
|
||
pub mod crates; | ||
pub mod deps; | ||
pub mod download; | ||
pub mod gn; | ||
pub mod manifest; | ||
pub mod paths; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters