Skip to content

Commit 493e2cf

Browse files
committed
feat: cached builds & meta
1 parent 97d2c6d commit 493e2cf

File tree

8 files changed

+122
-49
lines changed

8 files changed

+122
-49
lines changed

Cargo.lock

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@ bsdiff = "0.2.0"
2222
zip = "2.2.0"
2323
bzip2 = { version = "0.4", features = [] }
2424
toml = "0.8.19"
25+
sha1 = "0.10.6"
26+
hex = "0.4.3"

proc_macros/src/lib.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,17 @@ pub fn serial_snake(_attr: TokenStream, item: TokenStream) -> TokenStream {
2525
};
2626

2727
TokenStream::from(expanded)
28-
}
28+
}
29+
30+
#[proc_macro_attribute]
31+
pub fn serial_pascal(_attr: TokenStream, item: TokenStream) -> TokenStream {
32+
let input = parse_macro_input!(item as DeriveInput);
33+
34+
let expanded = quote! {
35+
#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq)]
36+
#[serde(rename_all = "PascalCase")]
37+
#input
38+
};
39+
40+
TokenStream::from(expanded)
41+
}

src/config.rs

+24
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use std::{fs, io, path::{Path, PathBuf}};
22

33
use proc_macros::serial_snake;
44

5+
use crate::version::schema::spigot::SpigotVersionRefs;
6+
57
#[serial_snake]
68
#[derive(Default)]
79
pub struct Config {
@@ -29,3 +31,25 @@ pub fn read_config<P: AsRef<Path>>(path: P) -> io::Result<Config> {
2931
|e| io::Error::new(io::ErrorKind::Other, e.to_string())
3032
)
3133
}
34+
35+
#[serial_snake]
36+
pub struct PatchedVersionMeta {
37+
pub patch_file: String,
38+
pub commit_hashes: SpigotVersionRefs,
39+
pub patch_hash: String,
40+
pub patched_jar_hash: String
41+
}
42+
43+
impl PatchedVersionMeta {
44+
pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Self> {
45+
let content = fs::read_to_string(path)?;
46+
47+
serde_json::from_str(&content).map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))
48+
}
49+
50+
pub fn write<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
51+
let json = serde_json::to_string_pretty(self)?;
52+
53+
fs::write(path, json)
54+
}
55+
}

src/main.rs

+41-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
use bin_patch_gen::build_tools::{
22
download_buildtools, find_file, run_buildtools, VANILLA_JAR_REGEX,
33
};
4-
use bin_patch_gen::config::Config;
4+
use bin_patch_gen::config::{Config, PatchedVersionMeta};
55
use bin_patch_gen::jar::extract_jar;
66
use bin_patch_gen::util::dir::create_temp_dir;
7-
use bin_patch_gen::util::TimeFormatter;
8-
use bin_patch_gen::version::fetch_versions;
9-
use bin_patch_gen::{config, jar, prepare_extraction_path, write_patch, MinecraftVersion, JAR_VERSIONS_PATH};
7+
use bin_patch_gen::util::{sha1, TimeFormatter};
8+
use bin_patch_gen::version::{fetch_spigot_version_meta, fetch_versions};
9+
use bin_patch_gen::{
10+
config, jar, prepare_extraction_path, write_patch, MinecraftVersion, JAR_VERSIONS_PATH,
11+
};
1012
use regex::Regex;
13+
use std::env::current_dir;
1114
use std::fs;
1215
use std::path::{Path, PathBuf};
1316
use tracing::info;
@@ -44,6 +47,16 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
4447

4548
let vanilla_jar_regex = Regex::new(VANILLA_JAR_REGEX)?;
4649

50+
let run_dir = if current_dir()?.ends_with("run") {
51+
current_dir()?
52+
} else {
53+
current_dir()?.join("run")
54+
};
55+
56+
if !run_dir.exists() {
57+
fs::create_dir_all(&run_dir)?;
58+
}
59+
4760
for version in versions {
4861
info!("Building Spigot for version {}...", version);
4962
let version_path = temp_dir.join(Path::new(&*version));
@@ -52,6 +65,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
5265

5366
let mc_version = MinecraftVersion::of(version.clone());
5467
let java_home = config.java_home(mc_version.get_java_version());
68+
let remote_meta = fetch_spigot_version_meta(version.clone()).await?;
69+
70+
let version_file = &run_dir.join(format!("{version}.json"));
71+
if version_file.exists() {
72+
let patched_meta = PatchedVersionMeta::read(version_file)?;
73+
74+
if remote_meta.refs == patched_meta.commit_hashes {
75+
info!("Already built version {version}, skipping");
76+
continue;
77+
}
78+
}
5579

5680
let result = run_buildtools(
5781
java_home,
@@ -115,9 +139,21 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
115139
result
116140
};
117141

142+
let patch_file = &run_dir.join(format!("{version}.patch"));
143+
118144
info!("Generating diff...");
119-
write_patch(vanilla_jar, spigot_jar, "bsdiff.patch")?;
145+
write_patch(&vanilla_jar, &spigot_jar, patch_file)?;
120146
info!("Diff generated!");
147+
148+
let patched_meta = PatchedVersionMeta {
149+
patch_file: patch_file.to_str().unwrap().to_string(),
150+
commit_hashes: remote_meta.refs,
151+
patch_hash: sha1(patch_file)?,
152+
patched_jar_hash: sha1(spigot_jar)?,
153+
};
154+
155+
patched_meta.write(version_file)?;
156+
info!("Wrote version metadata file!");
121157
}
122158

123159
Ok(())

src/util/mod.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
//! Module containing utilities.
22
3+
use std::fs::File;
4+
use std::io::{self, Read};
5+
use std::path::Path;
6+
37
use chrono::Local;
8+
use sha1::{Digest, Sha1};
49
use tracing_subscriber::fmt::format::Writer;
510
use tracing_subscriber::fmt::time::FormatTime;
611

@@ -12,4 +17,15 @@ impl FormatTime for TimeFormatter {
1217
let date = Local::now();
1318
write!(w, "{}", date.format("%H:%M:%S"))
1419
}
15-
}
20+
}
21+
22+
pub fn sha1<P: AsRef<Path>>(path: P) -> io::Result<String> {
23+
let mut bytes = vec![];
24+
let mut file = File::open(path)?;
25+
file.read_exact(&mut bytes)?;
26+
27+
let mut hasher = Sha1::new();
28+
hasher.update(bytes);
29+
30+
Ok(hex::encode(hasher.finalize()))
31+
}

src/version/mod.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
//! Fetches Minecraft versions from SpigotMC.
22
3-
mod schema;
3+
pub mod schema;
44

5-
use crate::version::schema::{Version, VersionMeta, VersionsResponse};
5+
use crate::version::schema::piston::{PistonVersion, PistonVersionMeta, PistonVersionsResponse};
66
use crate::{download_url, fetch_url, get_url, Reqwsult};
77
use regex::Regex;
8+
use schema::spigot::SpigotVersionMeta;
89
use scraper::{Html, Selector};
910
use std::path::Path;
1011
use tracing::warn;
@@ -55,14 +56,14 @@ pub async fn fetch_versions() -> Vec<String> {
5556
}))
5657
}
5758

58-
pub async fn fetch_piston_meta() -> Reqwsult<VersionsResponse> {
59+
pub async fn fetch_piston_meta() -> Reqwsult<PistonVersionsResponse> {
5960
let text = get_url(PISTON_META_URL).await?;
6061
Ok(serde_json::from_str(&text).unwrap_or_else(|err| {
6162
panic!("failed deserializing piston meta: {err:#?}")
6263
}))
6364
}
6465

65-
pub async fn fetch_version_meta(versions: VersionsResponse, version: String) -> Reqwsult<VersionMeta> {
66+
pub async fn fetch_piston_version_meta(versions: PistonVersionsResponse, version: String) -> Reqwsult<PistonVersionMeta> {
6667
let version = versions
6768
.versions
6869
.iter()
@@ -84,6 +85,16 @@ pub async fn fetch_version_meta(versions: VersionsResponse, version: String) ->
8485
)
8586
}
8687

87-
pub async fn download_version<P: AsRef<Path>>(version: Version, path: P) -> Reqwsult<()> {
88+
pub async fn download_version<P: AsRef<Path>>(version: PistonVersion, path: P) -> Reqwsult<()> {
8889
download_url(version.url, path).await
8990
}
91+
92+
pub async fn fetch_spigot_version_meta(version: String) -> Reqwsult<SpigotVersionMeta> {
93+
let url = format!("{VERSIONS_URL}/{version}.json");
94+
95+
Ok(
96+
serde_json::from_str(&(get_url(url).await?)).unwrap_or_else(|err| {
97+
panic!("failed deserializing version meta: {err:#?}")
98+
})
99+
)
100+
}

src/version/schema.rs

-37
This file was deleted.

0 commit comments

Comments
 (0)