Skip to content

Commit

Permalink
update main.rs
Browse files Browse the repository at this point in the history
  • Loading branch information
LiamGallagher737 committed Jul 15, 2024
1 parent f7d7d6a commit c40a79c
Showing 1 changed file with 95 additions and 101 deletions.
196 changes: 95 additions & 101 deletions tools/check_crate_updates/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
//! This tool loops over each manifest for the images and for each Bevy crate, checks the support
//! table in its readme to see if it can be updated, if so it updates the manifest.

use anyhow::anyhow;
use crate::manifest::Manifest;
use anyhow::{anyhow, Context};
use cached::proc_macro::cached;
use std::{env, fs, str::FromStr};
use std::{env, fs, path, str::FromStr};
use table_extract::Table;
use ureq::{Agent, AgentBuilder};

use crate::manifest::Manifest;

mod manifest;

const EXCLUDE_CRATES: &[&str] = &["bevy", "rand", "rand_chacha", "wasm-bindgen"];
Expand All @@ -32,116 +31,111 @@ fn main() -> anyhow::Result<()> {
.filter(|path| path.to_string_lossy().ends_with(".Cargo.toml"));

for path in manifest_paths {
let manifest_str = fs::read_to_string(&path)?;
let mut manifest = Manifest::from_str(&manifest_str)
.map_err(|e| anyhow!("Failed to parse manifest at {path:?}\n{e}"))?;

let Some(bevy) = manifest.get_dependency("bevy") else {
eprintln!("Skipping {path:?}, manifest does not contain Bevy");
continue;
if let Err(e) = handle_manifest(&path, agent.clone()) {
eprintln!("[ERROR] Error handling {path:?}: {e}");
};
}

let Some(bevy_version) = bevy.get_version() else {
// Most likely on main branch
eprintln!("Skipping {path:?}, invalid Bevy version");
continue;
};
println!("Complete");

let crates = manifest
.get_dependency_names()
.unwrap() // we know bevy exists so it can't be empty
.filter(|name| !EXCLUDE_CRATES.contains(name))
.map(|name| fetch_crate(name, agent.clone()))
.inspect(|res| {
if let Err(e) = res {
eprintln!("Error getting crate: {e}");
}
})
.filter_map(|res| res.ok());

let mut newest_versions = Vec::new();

println!("Bevy: {bevy_version}");
for c in crates {
let readme = match fetch_readme(&c, agent.clone()) {
Ok(r) => r,
Err(e) => {
eprintln!("Error getting readme: {e}");
continue;
}
};

let table = match find_support_table(&readme) {
Ok(t) => t,
Err(e) => {
eprintln!("{e}");
continue;
}
};

// currently assuming the bevy column is first
let mut matching = Vec::new();
for row in table.iter().map(|r| r.as_slice()) {
let bevy = extract_version_from_cell(&row[0]);
let others = extract_versions_from_cell(&row[1]);
for other in others {
if bevy.starts_with(bevy_version) {
matching.push((bevy.clone(), other));
}
}
}
Ok(())
}

if matching.is_empty() {
eprintln!("{} has no matches for {bevy_version}", c.data.name);
continue;
fn handle_manifest(path: &path::PathBuf, agent: Agent) -> anyhow::Result<()> {
let manifest_str = fs::read_to_string(path)?;
let mut manifest = Manifest::from_str(&manifest_str)
.map_err(|e| anyhow!("Failed to parse manifest at {path:?}\n{e}"))?;

let bevy_version = manifest
.get_dependency("bevy")
.ok_or_else(|| anyhow!("Manifest does not contain Bevy"))?
.get_version()
.ok_or_else(|| anyhow!("Invalid Bevy version"))?
.to_owned();

let newest_versions = manifest
.get_dependency_names()
.unwrap() // we know bevy exists so it can't be empty
.filter(|name| !EXCLUDE_CRATES.contains(name))
.map(|name| fetch_crate(name, agent.clone()))
.inspect(|res| {
if let Err(e) = res {
eprintln!("Error getting crate: {e}");
}

let newest = matching
.iter()
.map(|(_, other)| other.parse::<semver::VersionReq>())
.inspect(|res| {
if let Err(e) = res {
eprintln!("Failed to parse: {e}");
}
})
.filter_map(Result::ok)
.map(|semver| {
c.versions
.iter()
.map(|v| v.version.parse::<semver::Version>().unwrap())
.filter(|v| semver.matches(v))
.max()
.unwrap()
})
.max()
.unwrap();

println!(
"The most recent version for {} compatible with Bevy {bevy_version} is {newest}",
c.data.name
);

newest_versions.push((c.data.name, format!("={newest}")));
})
.filter_map(|res| res.ok())
.map(|c| {
(
c.data.name.clone(),
get_newest_version(c, &bevy_version, agent.clone()),
)
})
.filter_map(|(name, version)| version.map(|v| (name, v)).ok())
.collect::<Vec<_>>();

for (name, version) in newest_versions {
if !manifest
.get_dependency_mut(&name)
.unwrap() // name is a result from dep list so it must exist
.set_version(&version)
{
eprintln!("[WARNING] Failed to set value of {name} to {version}");
}
}

for (name, version) in newest_versions {
if !manifest
.get_dependency_mut(&name)
.unwrap() // name is a result from dep list so it must exist
.set_version(&version)
{
eprintln!("Failed to set value of {name} tp {version}");
Ok(())
}

fn get_newest_version(
c: CrateResponse,
bevy_version: &str,
agent: Agent,
) -> anyhow::Result<String> {
let readme = fetch_readme(&c, agent.clone()).with_context(|| "Failed to get readme")?;
let table = find_support_table(&readme).with_context(|| "Failed to find support table")?;

// currently assuming the bevy column is first
let mut matching = Vec::new();
for row in table.iter().map(|r| r.as_slice()) {
let bevy = extract_version_from_cell(&row[0]);
let others = extract_versions_from_cell(&row[1]);
for other in others {
if bevy.starts_with(bevy_version) {
matching.push((bevy.clone(), other));
}
}
}

if let Err(e) = fs::write(&path, manifest.to_string()) {
eprintln!("Failed to write to {path:?}: {e}");
}
if matching.is_empty() {
return Err(anyhow!("{} has no matches for {bevy_version}", c.data.name));
}

println!("Complete");
let newest = matching
.iter()
.map(|(_, other)| other.parse::<semver::VersionReq>())
.inspect(|res| {
if let Err(e) = res {
eprintln!("[WARNING] Failed to parse: {e}");
}
})
.filter_map(Result::ok)
.map(|semver| {
c.versions
.iter()
.map(|v| v.version.parse::<semver::Version>().unwrap())
.filter(|v| semver.matches(v))
.max()
.unwrap()
})
.max()
.unwrap();

Ok(())
println!(
"[INFO] The most recent version for {} compatible with Bevy {bevy_version} is {newest}",
c.data.name
);

Ok(format!("={newest}"))
}

#[cached(
Expand Down

0 comments on commit c40a79c

Please sign in to comment.