Skip to content

Commit

Permalink
Hash assets two times
Browse files Browse the repository at this point in the history
to get a unique hash when there are no changes in the file, but a referenced asset has a new hash
  • Loading branch information
prasmussen committed Jul 19, 2024
1 parent 6efbdee commit 9a33ec7
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 46 deletions.
38 changes: 30 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
55 changes: 32 additions & 23 deletions src/asset_hasher.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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::<Vec<_>>()
.join("\n");
Expand Down Expand Up @@ -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()
}
Expand Down
58 changes: 43 additions & 15 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
&current_dir,
&env,
);

// Hash again now that assets contains the correct hash
hash_assets_helper(
&asset_hasher,
&rust_builder,
&web_builder,
&script,
&current_dir,
&env,
);
}
}

Expand Down Expand Up @@ -274,6 +277,31 @@ fn main() {
}
}

fn hash_assets_helper(
asset_hasher: &AssetHasher,
rust_builder: &RustBuilder,
web_builder: &WebBuilder,
script: &Option<String>,
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()
}
Expand Down

0 comments on commit 9a33ec7

Please sign in to comment.