Skip to content

Commit 2c708d2

Browse files
committed
rust: produce install_only tar.gz when fetching release artifacts
Currently, we produce these .tar.gz archives part of CI. This adds complexity to CI and there isn't much value in having the .tar.gz CI artifacts before release since they are redundant with the .tar.zst archive content. This commit adds Rust code for normalizing the .tar.zst files to the .tar.gz install_only archives. The Rust code should be comparable to the Python code. However, it does result in the creation of more install_only archives.
1 parent edbd9e0 commit 2c708d2

File tree

4 files changed

+116
-11
lines changed

4 files changed

+116
-11
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ anyhow = "1"
99
bytes = "1.1"
1010
clap = "2"
1111
duct = "0"
12+
flate2 = "1"
1213
futures = "0"
1314
goblin = "0"
1415
octocrab = { version = "0", features = ["rustls"] }

src/github.rs

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

55
use {
6-
crate::release::RELEASE_TRIPLES,
6+
crate::release::{produce_install_only, RELEASE_TRIPLES},
77
anyhow::{anyhow, Result},
88
clap::ArgMatches,
99
futures::StreamExt,
@@ -102,22 +102,56 @@ pub async fn command_fetch_release_distributions(args: &ArgMatches<'_>) -> Resul
102102

103103
let name = zf.name().to_string();
104104

105-
if let Some(release) = RELEASE_TRIPLES.iter().find_map(|(triple, release)| {
105+
if let Some((triple, release)) = RELEASE_TRIPLES.iter().find_map(|(triple, release)| {
106106
if name.contains(triple) {
107-
Some(release)
107+
Some((triple, release))
108108
} else {
109109
None
110110
}
111111
}) {
112-
if release.suffixes.iter().any(|suffix| name.contains(suffix)) {
113-
let dest_path = dest_dir.join(&name);
114-
let mut buf = vec![];
115-
zf.read_to_end(&mut buf)?;
116-
std::fs::write(&dest_path, &buf)?;
117-
118-
println!("releasing {}", name);
112+
let stripped_name = if let Some(s) = name.strip_suffix(".tar.zst") {
113+
s
119114
} else {
115+
println!("{} not a .tar.zst artifact", name);
116+
continue;
117+
};
118+
119+
let stripped_name = &stripped_name[0..stripped_name.len() - "-YYYYMMDDTHHMM".len()];
120+
121+
let triple_start = stripped_name
122+
.find(triple)
123+
.expect("validated triple presence above");
124+
125+
let build_suffix = &stripped_name[triple_start + triple.len() + 1..];
126+
127+
if !release
128+
.suffixes
129+
.iter()
130+
.any(|suffix| build_suffix == *suffix)
131+
{
120132
println!("{} not a release artifact for triple", name);
133+
continue;
134+
}
135+
136+
let dest_path = dest_dir.join(&name);
137+
let mut buf = vec![];
138+
zf.read_to_end(&mut buf)?;
139+
std::fs::write(&dest_path, &buf)?;
140+
141+
println!("releasing {}", name);
142+
143+
if build_suffix == release.install_only_suffix {
144+
println!("producing install_only archive from {}", name);
145+
146+
let dest_path = produce_install_only(&dest_path)?;
147+
148+
println!(
149+
"releasing {}",
150+
dest_path
151+
.file_name()
152+
.expect("should have file name")
153+
.to_string_lossy()
154+
);
121155
}
122156
} else {
123157
println!("{} does not match any registered release triples", name);

src/release.rs

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,15 @@
22
// License, v. 2.0. If a copy of the MPL was not distributed with this
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

5-
use {once_cell::sync::Lazy, std::collections::BTreeMap};
5+
use {
6+
anyhow::Result,
7+
once_cell::sync::Lazy,
8+
std::{
9+
collections::BTreeMap,
10+
io::{BufRead, Read, Write},
11+
path::{Path, PathBuf},
12+
},
13+
};
614

715
/// Describes a release for a given target triple.
816
pub struct TripleRelease {
@@ -128,3 +136,64 @@ pub static RELEASE_TRIPLES: Lazy<BTreeMap<&'static str, TripleRelease>> = Lazy::
128136

129137
h
130138
});
139+
140+
/// Convert a .tar.zst archive to an install only .tar.gz archive.
141+
pub fn convert_to_install_only<W: Write>(reader: impl BufRead, writer: W) -> Result<W> {
142+
let dctx = zstd::stream::Decoder::new(reader)?;
143+
144+
let mut tar_in = tar::Archive::new(dctx);
145+
146+
let writer = flate2::write::GzEncoder::new(writer, flate2::Compression::default());
147+
148+
let mut builder = tar::Builder::new(writer);
149+
150+
for entry in tar_in.entries()? {
151+
let mut entry = entry?;
152+
153+
if !entry.path_bytes().starts_with(b"python/install/") {
154+
continue;
155+
}
156+
157+
let mut data = vec![];
158+
entry.read_to_end(&mut data)?;
159+
160+
let path = entry.path()?;
161+
let new_path = PathBuf::from("python").join(path.strip_prefix("python/install/")?);
162+
163+
let mut header = entry.header().clone();
164+
header.set_path(&new_path)?;
165+
header.set_cksum();
166+
167+
builder.append(&header, std::io::Cursor::new(data))?;
168+
}
169+
170+
Ok(builder.into_inner()?.finish()?)
171+
}
172+
173+
pub fn produce_install_only(tar_zst_path: &Path) -> Result<PathBuf> {
174+
let buf = std::fs::read(tar_zst_path)?;
175+
176+
let gz_data = convert_to_install_only(std::io::Cursor::new(buf), std::io::Cursor::new(vec![]))?
177+
.into_inner();
178+
179+
let filename = tar_zst_path
180+
.file_name()
181+
.expect("should have filename")
182+
.to_string_lossy();
183+
184+
let mut name_parts = filename
185+
.split('-')
186+
.map(|x| x.to_string())
187+
.collect::<Vec<_>>();
188+
let parts_len = name_parts.len();
189+
190+
name_parts[parts_len - 2] = "install_only".to_string();
191+
192+
let install_only_name = name_parts.join("-");
193+
let install_only_name = install_only_name.replace(".tar.zst", ".tar.gz");
194+
195+
let dest_path = tar_zst_path.with_file_name(install_only_name);
196+
std::fs::write(&dest_path, &gz_data)?;
197+
198+
Ok(dest_path)
199+
}

0 commit comments

Comments
 (0)