Skip to content

Commit

Permalink
seperate manifest module
Browse files Browse the repository at this point in the history
  • Loading branch information
LiamGallagher737 committed Jul 15, 2024
1 parent 71d9a8c commit 1fe2bec
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 25 deletions.
53 changes: 28 additions & 25 deletions tools/check_crate_updates/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
//! 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 cached::proc_macro::cached;
use std::{env, fs};
use std::{env, fs, 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"];

fn main() -> anyhow::Result<()> {
Expand All @@ -26,29 +33,23 @@ fn main() -> anyhow::Result<()> {

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

// skip if no version - using main branch
if !manifest["dependencies"]["bevy"]
.as_inline_table()
.unwrap()
.contains_key("version")
{
println!("Skipping {path:?}");
let Some(bevy) = manifest.get_dependency("bevy") else {
eprintln!("Skipping {path:?}, manifest does not contain Bevy");
continue;
}
};

let bevy_version = manifest["dependencies"]["bevy"]["version"]
.as_str()
.unwrap();
let Some(bevy_version) = bevy.get_version() else {
// Most likely on main branch
eprintln!("Skipping {path:?}, invalid Bevy version");
continue;
};

let crates = manifest["dependencies"]
.as_table()
.unwrap()
.iter()
.map(|(name, _)| name)
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| {
Expand Down Expand Up @@ -124,10 +125,12 @@ fn main() -> anyhow::Result<()> {
}

for (name, version) in newest_versions {
if let Some(table) = manifest["dependencies"][&name].as_inline_table_mut() {
table["version"] = version.into();
} else {
manifest["dependencies"][name] = toml_edit::value(version);
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}");
}
}

Expand All @@ -145,7 +148,7 @@ fn main() -> anyhow::Result<()> {
result = true,
ty = "cached::SizedCache<String, CrateResponse>",
create = "{ cached::SizedCache::with_size(20) }",
convert = r#"{ name.to_string() }"#
convert = r#"{ name.to_owned() }"#
)]
fn fetch_crate(name: &str, agent: Agent) -> anyhow::Result<CrateResponse> {
agent
Expand All @@ -160,7 +163,7 @@ fn fetch_crate(name: &str, agent: Agent) -> anyhow::Result<CrateResponse> {
result = true,
ty = "cached::SizedCache<String, String>",
create = "{ cached::SizedCache::with_size(20) }",
convert = r#"{ c.data.name.to_string() }"#
convert = r#"{ c.data.name.clone() }"#
)]
fn fetch_readme(c: &CrateResponse, agent: Agent) -> anyhow::Result<String> {
let path = &c.versions[0].readme_path; // index 0 is latest
Expand Down
81 changes: 81 additions & 0 deletions tools/check_crate_updates/src/manifest.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use std::{fmt::Display, str::FromStr};

pub struct Manifest(toml_edit::DocumentMut);

impl Manifest {
/// Gets the dependency from the manifest if it exists
pub fn get_dependency(&self, name: &str) -> Option<Dependency> {
self.0
.get("dependencies")
.and_then(|dep| dep.get(name))
.map(|dep| Dependency(dep))
}

/// Gets the dependency mutably from the manifest if it exists
pub fn get_dependency_mut(&mut self, name: &str) -> Option<DependencyMut> {
self.0
.get_mut("dependencies")
.and_then(|dep| dep.get_mut(name))
.map(|dep| DependencyMut(dep))
}

/// Gets the names of all the dependencies from the manifest
pub fn get_dependency_names<'a>(&'a self) -> Option<impl Iterator<Item = &'a str>> {
self.0
.get("dependencies")
.and_then(|item| item.as_table())
.map(|table| table.iter().map(|(name, _)| name))
}
}

pub struct Dependency<'a>(&'a toml_edit::Item);
pub struct DependencyMut<'a>(&'a mut toml_edit::Item);

impl<'a> Dependency<'a> {
/// Gets the version of the dependency by searching first
/// the value of the entry and then as a inline table
pub fn get_version(&self) -> Option<&'a str> {
if let Some(version) = self.0.get("version").and_then(|i| i.as_str()) {
Some(version)
} else if let Some(table) = self.0.as_inline_table() {
table.get("version").and_then(|i| i.as_str())
} else {
None
}
}
}

impl<'a> DependencyMut<'a> {
/// Sets the version of the dependency by searching first
/// the value of the entry and then as a inline table.
/// Returns whether it was successful
pub fn set_version(&mut self, version: &str) -> bool {
if let Some(value) = self.0.get_mut("version").and_then(|i| i.as_value_mut()) {
*value = version.into();
true
} else if let Some(value) = self
.0
.as_inline_table_mut()
.and_then(|table| table.get_mut("version"))
{
*value = version.into();
true
} else {
false
}
}
}

impl FromStr for Manifest {
type Err = toml_edit::TomlError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
s.parse::<toml_edit::DocumentMut>().map(|doc| Manifest(doc))
}
}

impl Display for Manifest {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0.to_string())
}
}

0 comments on commit 1fe2bec

Please sign in to comment.