Skip to content

Commit

Permalink
use the github asset url information
Browse files Browse the repository at this point in the history
use the github asset url information so we only download things it claims to have

Test Plan:

cargo test

local run and check the download and cache still work, notice the fetching message on first run

```
# Download
$ USE_BUCK2_VERSION=2023-07-15 cargo run -- --version
    Finished dev [unoptimized + debuginfo] target(s) in 0.03s
     Running `target/debug/buckle --version`
buckle: fetching buck2-x86_64-unknown-linux-gnu.zst 2023-07-15
buck2 22862e81827fad189f124d677c623d7ec1772cc6 <local>

# see its cached
$ USE_BUCK2_VERSION=2023-07-15 cargo run -- --version
Sat 22 Jul 19:23:14 BST 2023
    Finished dev [unoptimized + debuginfo] target(s) in 0.04s
     Running `target/debug/buckle --version`
buck2 22862e81827fad189f124d677c623d7ec1772cc6 <local>
Sat 22 Jul 19:23:14 BST 2023 [Exit: 0] alex@fridge:~/loca
```
  • Loading branch information
ahornby committed Jul 22, 2023
1 parent 0f5f55f commit 7332496
Showing 1 changed file with 41 additions and 18 deletions.
59 changes: 41 additions & 18 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use std::os::unix::fs::PermissionsExt;
#[cfg(unix)]
use std::time::SystemTime;

const BASE_URL: &str = "https://github.com/facebook/buck2/releases/download";
const BUCK_RELEASE_URL: &str = "https://github.com/facebook/buck2/tags";

fn get_buckle_dir() -> Result<PathBuf, Error> {
Expand Down Expand Up @@ -81,6 +80,13 @@ fn get_buck2_project_root() -> Option<&'static Path> {
path.as_deref()
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct Asset {
pub name: String,
pub browser_download_url: Url,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct Release {
Expand All @@ -101,7 +107,7 @@ pub struct Release {
pub created_at: Option<String>,
pub published_at: Option<String>,
pub author: serde_json::Value,
pub assets: Vec<serde_json::Value>,
pub assets: Vec<Asset>,
}

fn get_releases(path: &Path) -> Result<Vec<Release>, Error> {
Expand Down Expand Up @@ -156,16 +162,33 @@ fn get_arch() -> Result<&'static str, Error> {
fn download_http(version: String, output_dir: &Path) -> Result<PathBuf, Error> {
let releases = get_releases(output_dir)?;
let mut dir_path = output_dir.to_path_buf();
let mut release_found = false;

let mut unpackable = None;
let mut verbatim = vec![];
let arch = get_arch()?;

for release in releases {
if release.tag_name == version {
dir_path.push(release.target_commitish);
release_found = true;
if release.name.as_ref() == Some(&version) {
if release.tag_name == version {
dir_path.push(release.target_commitish);
}
for asset in release.assets {
let name = asset.name;
let url = asset.browser_download_url;
if name == format!("buck2-{}.zst", arch) {
unpackable = Some((name, url));
} else if name == "prelude" {
verbatim.push((name, url));
}
}
}
}
if !release_found {

let (name, url) = if let Some(unpackable) = unpackable {
unpackable
} else {
return Err(anyhow!("{version} was not available. Please check '{BUCK_RELEASE_URL}' for available releases."));
}
};

let binary_path: PathBuf = [&dir_path, Path::new("buck2")].iter().collect();
if binary_path.exists() {
Expand All @@ -176,21 +199,21 @@ fn download_http(version: String, output_dir: &Path) -> Result<PathBuf, Error> {
// Create the release directory if it doesn't exist
fs::create_dir_all(&dir_path).with_context(|| anyhow!("problem creating {:?}", dir_path))?;

{
// Fetch the prelude hash and store it, do this before the binary so we don't see a partial hash
for (name, url) in verbatim {
// Fetch the verbatim items hash and store, do this before the binary so we don't see a partial hash
// We do this as the complete executable is atomic via tmp_file rename
let prelude_path: PathBuf = [&dir_path, Path::new("prelude_hash")].iter().collect();
let resp = reqwest::blocking::get(format!("{BASE_URL}/{version}/prelude_hash"))?;
let mut prelude_hash = File::create(prelude_path)?;
prelude_hash.write_all(&resp.bytes()?)?;
prelude_hash.flush()?;
let verbatim_path: PathBuf = [&dir_path, Path::new(&name)].iter().collect();
let resp = reqwest::blocking::get(url)?;
let mut verbatim_file = File::create(&verbatim_path)
.with_context(|| anyhow!("problem creating {:?}", verbatim_path))?;
verbatim_file.write_all(&resp.bytes()?)?;
verbatim_file.flush()?;
}

// Fetch the buck2 archive, decode it, make it executable
let mut tmp_file = NamedTempFile::new_in(&dir_path)?;
let arch = get_arch()?;
eprintln!("buckle: fetching buck2 {version}");
let resp = reqwest::blocking::get(format!("{BASE_URL}/{version}/buck2-{arch}.zst"))?;
eprintln!("buckle: fetching {name} {version}");
let resp = reqwest::blocking::get(url)?;
zstd::stream::copy_decode(resp, &tmp_file)?;
tmp_file.flush()?;
#[cfg(unix)]
Expand Down

0 comments on commit 7332496

Please sign in to comment.