diff --git a/Cargo.lock b/Cargo.lock index 9fe5030..211da01 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "atty" version = "0.2.14" @@ -319,7 +328,7 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" dependencies = [ - "aho-corasick", + "aho-corasick 0.7.18", "bstr", "fnv", "log", @@ -472,9 +481,9 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "mime" @@ -569,6 +578,7 @@ dependencies = [ "httparse", "mime_guess", "notify", + "regex", "serde", "sha2", "tempfile", @@ -631,20 +641,32 @@ dependencies = [ [[package]] name = "regex" -version = "1.6.0" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ - "aho-corasick", + "aho-corasick 1.1.3", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick 1.1.3", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.27" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "remove_dir_all" diff --git a/Cargo.toml b/Cargo.toml index 6659c92..d47d524 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ http = "0.2.8" httparse = "1.8.0" mime_guess = "2.0.4" notify = "5.0.0-pre.16" +regex = "1.10.5" serde = { version = "1.0.144", features = ["derive"] } sha2 = "0.10.2" tempfile = "3.3.0" diff --git a/src/asset_hasher.rs b/src/asset_hasher.rs index 89d2615..0b50e20 100644 --- a/src/asset_hasher.rs +++ b/src/asset_hasher.rs @@ -1,5 +1,6 @@ use crate::util::file_util; use crate::ProjectInfo; +use regex::Regex; use sha2::Digest; use sha2::Sha256; use std::ffi::OsStr; @@ -155,21 +156,37 @@ impl AssetHasher { .content .lines() .map(|line| { - assets.iter().fold(line.to_string(), |acc, asset| { - if line.contains(&asset.uri_with_placeholder_hash()) { - println!( - "Replacing uri {} -> {} in {}", - asset.uri_with_placeholder_hash(), - asset.uri_with_hash(), - file_path.display() - ); - - file_was_changed = true; - acc.replace(&asset.uri_with_placeholder_hash(), &asset.uri_with_hash()) - } else { - acc - } - }) + assets + .iter() + .fold(line.to_string(), |modified_line, asset| { + let group_name = "hash"; + let pattern = + format!(r"{}\?hash=(?<{}>[a-zA-Z0-9]+)", asset.uri, group_name); + + let captured_hash = Regex::new(&pattern) + .unwrap() + .captures(&modified_line) + .map(|groups| groups[group_name].to_string()); + + let new_hash = asset.short_hash(); + + match captured_hash { + Some(old_hash) if new_hash != old_hash => { + println!( + "Hash asset [{}]: Replacing hash '{}' -> '{}' in file '{}'", + asset.uri, + old_hash, + asset.short_hash(), + file_path.file_name().unwrap().to_string_lossy(), + ); + + file_was_changed = true; + modified_line.replace(&old_hash, &asset.short_hash()) + } + + _ => modified_line, + } + }) }) .collect::>() .join("\n"); @@ -200,14 +217,6 @@ pub struct HashedAsset { } impl HashedAsset { - fn uri_with_placeholder_hash(&self) -> String { - format!("{}?hash=checksum", self.asset.uri) - } - - fn uri_with_hash(&self) -> String { - format!("{}?hash={}", self.asset.uri, self.short_hash()) - } - fn short_hash(&self) -> String { self.hash[..7].to_string() } diff --git a/src/main.rs b/src/main.rs index 7ce1044..9c87e1e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -172,21 +172,24 @@ fn main() { let asset_hasher = AssetHasher::new(asset_hasher::Config::from_project_info(&project_info)); - let assets = asset_hasher.collect_hashed_dist_assets().unwrap(); - asset_hasher - .replace_checksum_in_source_files(&assets) - .unwrap(); - - rust_builder.run().expect("Rust build failed"); - web_builder.run().expect("Web build failed"); - - if let Some(script_name) = &script { - let script_path = current_dir.join(script_name); - let script_runner = ScriptRunner::new(script_path, &env); - script_runner - .run(script_runner::Event::AfterAssetHash) - .expect("Post build runner failed"); - } + hash_assets_helper( + &asset_hasher, + &rust_builder, + &web_builder, + &script, + ¤t_dir, + &env, + ); + + // Hash again now that assets contains the correct hash + hash_assets_helper( + &asset_hasher, + &rust_builder, + &web_builder, + &script, + ¤t_dir, + &env, + ); } } @@ -274,6 +277,31 @@ fn main() { } } +fn hash_assets_helper( + asset_hasher: &AssetHasher, + rust_builder: &RustBuilder, + web_builder: &WebBuilder, + script: &Option, + current_dir: &PathBuf, + env: &Env, +) { + let assets = asset_hasher.collect_hashed_dist_assets().unwrap(); + asset_hasher + .replace_checksum_in_source_files(&assets) + .unwrap(); + + rust_builder.run().expect("Rust build failed"); + web_builder.run().expect("Web build failed"); + + if let Some(script_name) = &script { + let script_path = current_dir.join(script_name); + let script_runner = ScriptRunner::new(script_path, &env); + script_runner + .run(script_runner::Event::AfterAssetHash) + .expect("Post build runner failed"); + } +} + fn get_current_dir() -> PathBuf { std::env::current_dir().unwrap() }