Skip to content

Commit

Permalink
Don't report conflicting files lint on identical files or on shared a…
Browse files Browse the repository at this point in the history
…sset folders
  • Loading branch information
jieyouxu committed Aug 14, 2023
1 parent 2f08dac commit f02c749
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 18 deletions.
5 changes: 3 additions & 2 deletions src/gui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -851,8 +851,9 @@ impl App {
.show(
ui,
|ui| {
mods.iter().for_each(|m| {
ui.label(&m.url);
mods.iter().for_each(|(mod_spec, hash)| {
ui.label(RichText::new(format!("Mod {} modifies the asset with hash: ", mod_spec.url)));
ui.label(RichText::new(hex::encode(hash)).code());
});
},
);
Expand Down
70 changes: 55 additions & 15 deletions src/mod_lint.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
use std::collections::{BTreeMap, BTreeSet};
use std::io::BufReader;
use std::io::{BufReader, Cursor};
use std::path::{Path, PathBuf};

use anyhow::{Context, Result};
use sha2::{Digest, Sha256};
use tracing::{info, span, trace, Level};

use crate::providers::ModSpecification;
use crate::{lint_get_all_files_from_data, open_file, GetAllFilesFromDataError, PakOrNotPak};

#[derive(Debug, Clone)]
pub struct ModLintReport {
pub conflicting_mods: BTreeMap<String, BTreeSet<ModSpecification>>,
pub conflicting_mods: BTreeMap<String, BTreeSet<(ModSpecification, Vec<u8>)>>,
pub asset_register_bin_mods: BTreeMap<ModSpecification, BTreeSet<String>>,
pub shader_file_mods: BTreeMap<ModSpecification, BTreeSet<String>>,
pub outdated_pak_version_mods: BTreeMap<ModSpecification, repak::Version>,
Expand All @@ -20,12 +21,13 @@ pub struct ModLintReport {
}

pub fn lint(mods: &[(ModSpecification, PathBuf)]) -> Result<ModLintReport> {
let span = span!(Level::TRACE, "mod_lint", ?mods);
trace!(?mods);
let span = span!(Level::TRACE, "mod_lint");
let _enter = span.enter();

info!(target: "mod_lint", "beginning mods lint");

let mut added_path_modifiers = BTreeMap::new();
let mut per_path_modifiers = BTreeMap::new();
let mut asset_register_bin_mods = BTreeMap::new();
let mut shader_file_mods = BTreeMap::new();
let mut outdated_pak_version_mods = BTreeMap::new();
Expand Down Expand Up @@ -65,10 +67,7 @@ pub fn lint(mods: &[(ModSpecification, PathBuf)]) -> Result<ModLintReport> {
archive_with_multiple_paks_mods.insert(mod_spec.clone());
}

let (ref first_pak_path, ref mut first_pak_buf) = pak_bufs[0];
trace!(?first_pak_path);

let pak = repak::PakReader::new_any(first_pak_buf, None)?;
let pak = repak::PakReader::new_any(&mut pak_bufs[0].1, None)?;

if pak.version() < repak::Version::V11 {
outdated_pak_version_mods.insert(mod_spec.clone(), pak.version());
Expand All @@ -77,18 +76,32 @@ pub fn lint(mods: &[(ModSpecification, PathBuf)]) -> Result<ModLintReport> {
let mount = Path::new(pak.mount_point());

for p in pak.files() {
trace!(?p);
let j = mount.join(&p);
let new_path = j
.strip_prefix("../../../")
.context("prefix does not match")?;
let new_path_str = &new_path.to_string_lossy().replace('\\', "/");
let lowercase = new_path_str.to_ascii_lowercase();
added_path_modifiers

let mut buf = vec![];
let mut writer = Cursor::new(&mut buf);
pak.read_file(&p, &mut pak_bufs[0].1, &mut writer)?;

trace!("pak read okay");

let mut hasher = Sha256::new();
trace!("buf.len() = {}", buf.len());
hasher.update(&buf);
let hash = hasher.finalize().to_vec();
trace!("hash = {}", hex::encode(&hash));

per_path_modifiers
.entry(lowercase.clone())
.and_modify(|modifiers: &mut BTreeSet<ModSpecification>| {
modifiers.insert(mod_spec.clone());
.and_modify(|modifiers: &mut BTreeSet<(ModSpecification, Vec<u8>)>| {
modifiers.insert((mod_spec.clone(), hash.clone()));
})
.or_insert_with(|| [mod_spec.clone()].into());
.or_insert_with(|| [(mod_spec.clone(), hash)].into());

if let Some(filename) = new_path.file_name() {
if filename == "AssetRegistry.bin" {
Expand All @@ -112,10 +125,37 @@ pub fn lint(mods: &[(ModSpecification, PathBuf)]) -> Result<ModLintReport> {
}
}

let conflicting_mods = added_path_modifiers
const CONFLICTING_MODS_LINT_WHITELIST: [&str; 1] = ["fsd/content/_interop"];

let conflicting_mods = per_path_modifiers
.into_iter()
.filter(|(_, modifiers)| modifiers.len() > 1)
.collect::<BTreeMap<String, BTreeSet<ModSpecification>>>();
.filter(|(p, _)| {
for whitelisted_path in CONFLICTING_MODS_LINT_WHITELIST {
if p.starts_with(whitelisted_path) {
return false;
}
}
true
})
.filter(|(_, modifiers)| {
modifiers.len() > 1 && {
let mut first_hash = None;
for (_, hash) in modifiers {
match first_hash {
None => {
first_hash = Some(hash);
}
Some(first_hash) => {
if hash != first_hash {
return true;
}
}
}
}
false
}
})
.collect::<BTreeMap<String, BTreeSet<(ModSpecification, Vec<u8>)>>>();

Ok(ModLintReport {
conflicting_mods,
Expand Down
Binary file modified test_mod_batches/lints/A.pak
Binary file not shown.
1 change: 1 addition & 0 deletions test_mod_batches/lints/A/FSD/Content/A.uexp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
a
Binary file modified test_mod_batches/lints/B.pak
Binary file not shown.
1 change: 1 addition & 0 deletions test_mod_batches/lints/B/FSD/Content/A.uexp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
b
9 changes: 8 additions & 1 deletion tests/lint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,16 @@ pub fn test_lint_conflicting_files() {
let a_spec = ModSpecification {
url: "A".to_string(),
};
// a\n
let a_hash =
hex::decode("87428fc522803d31065e7bce3cf03fe475096631e5e07bbd7a0fde60c4cf25c7").unwrap();

let b_spec = ModSpecification {
url: "B".to_string(),
};
// b\n
let b_hash =
hex::decode("0263829989b6fd954f72baaf2fc64bc2e2f01d692d4de72986ea808f6e99813f").unwrap();
let mods = vec![(a_spec.clone(), a_path), (b_spec.clone(), b_path)];

let ModLintReport {
Expand All @@ -28,7 +35,7 @@ pub fn test_lint_conflicting_files() {

assert_eq!(
conflicting_mods.get("fsd/content/a.uexp"),
Some(&[a_spec, b_spec].into())
Some(&[(a_spec, a_hash), (b_spec, b_hash)].into())
);
}

Expand Down

0 comments on commit f02c749

Please sign in to comment.