use std::process::Command;
use std::io::prelude::*;
use std::fs::File;
use temp_dir::TempDir;
use anyhow::Result;
use merlon::package::{*, init::*, manifest::*, distribute::ExportOptions};
const DECOMP_REV: &str = "7a9df943ad079e7b19df0f8690bdc92e2beed964";
#[path = "rom.rs"]
mod rom;
#[test]
fn initialising_package_gives_decomp_dependency() -> Result<()> {
let tempdir = TempDir::new()?;
let pkg_path = tempdir.path().join("test");
let package = Package::new("Test", pkg_path)?;
let mut registry = Registry::new();
let id = registry.register(package)?;
assert_eq!(registry.all_dependencies()?.len(), 0);
let package = registry.get_or_error(id)?;
let _initialised = package.clone().to_initialised(InitialiseOptions {
baserom: rom::baserom(),
rev: Some(DECOMP_REV.to_string()),
})?;
let all_dependencies = registry.all_dependencies()?;
assert_eq!(all_dependencies.len(), 1);
assert!(matches!(all_dependencies.iter().next(), Some(Dependency::Decomp { .. })));
Ok(())
}
#[test]
#[ignore] fn sync_complex_dependency_graph_to_repo() -> Result<()> {
let tempdir = TempDir::new()?;
let dir_path = tempdir.path();
let mut registry = Registry::new();
let mut create_and_register_package = |name: &str| -> Result<Id> {
let pkg_path = dir_path.join(name);
let package = Package::new(name, pkg_path)?;
let mut file = File::create(package.path().join("patches/0001-test.patch")).unwrap();
write!(&mut file, "{}", touch_file_patch(&format!("src/merlon_test_{name}"))).unwrap();
let id = registry.register(package)?;
Ok(id)
};
let root = create_and_register_package("Root")?;
let dep_a = create_and_register_package("DepA")?;
let dep_b = create_and_register_package("DepB")?;
let shared_dep = create_and_register_package("SharedDep")?;
dbg!(&root, &dep_a, &dep_b, &shared_dep);
registry.add_direct_dependency(root, dep_a)?;
registry.add_direct_dependency(root, dep_b)?;
registry.add_direct_dependency(dep_a, shared_dep)?;
let root_package = registry.get_or_error(root)?.clone();
let mut initialised = root_package.clone().to_initialised(InitialiseOptions {
baserom: rom::baserom(),
rev: Some(DECOMP_REV.to_string()),
})?;
initialised.set_registry(registry); initialised.setup_git_branches()?;
initialised.update_patches_dir()?;
let root_patches = initialised.package().path().join("patches");
dbg!(root_patches
.read_dir()?
.map(|e| Ok(e?.file_name()))
.collect::<Result<Vec<_>>>()?
);
assert_eq!(root_patches.read_dir()?.count(), 1);
assert!(initialised.subrepo_path().join("src/merlon_test_Root.c").is_file());
assert!(initialised.subrepo_path().join("src/merlon_test_DepA.c").is_file());
assert!(initialised.subrepo_path().join("src/merlon_test_DepB.c").is_file());
assert!(initialised.subrepo_path().join("src/merlon_test_SharedDep.c").is_file());
Ok(())
}
fn gen_random_commit_hash_for_patch() -> String {
use rand::Rng;
let mut rng = rand::thread_rng();
let mut hash = String::with_capacity(40);
for _ in 0..40 {
hash.push(rng.gen_range(b'0'..b'9') as char);
}
hash
}
fn touch_file_patch(filename: &str) -> String {
let hash = gen_random_commit_hash_for_patch();
format!(r#"From {hash} Mon Sep 17 00:00:00 2001
From: Merlon test <merlontest@nanaian.town>
Date: Wed, 26 Apr 2023 22:40:19 +0100
Subject: test
---
{filename}.c | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 {filename}
diff --git a/{filename} b/{filename}
new file mode 100644
index 0000000..e69de29
--
2.39.0"#)
}
#[test]
fn single_dependency() -> Result<()> {
let tempdir = TempDir::new()?;
let root = Package::new("Root", tempdir.path().join("root"))?;
let mut root = root.to_initialised(InitialiseOptions {
baserom: rom::baserom(),
rev: Some(DECOMP_REV.to_string()),
})?;
let dependency = Package::new("Dependency", tempdir.path().join("dependency"))?;
let mut file = File::create(dependency.path().join("patches/0001-set-bSkipIntro-to-true.patc"))?;
write!(&mut file, "{}", skip_intro_patch())?;
root.add_dependency(AddDependencyOptions {
path: dependency.path().to_path_buf(),
})?;
root.setup_git_branches()?;
let output = Command::new("git")
.arg("log")
.arg("-1")
.arg("--pretty=format:%s")
.current_dir(root.subrepo_path())
.output()?;
let head_commit = String::from_utf8(output.stdout)?.trim().to_string();
assert_eq!(&head_commit, "set bSkipIntro to true");
let distributable = root.package().export_distributable(ExportOptions {
baserom: Some(rom::baserom()),
output: Some(tempdir.path().join("output.merlon")),
})?;
distributable.open_scoped(rom::baserom(), |package| {
let manifest = package.manifest()?;
assert_eq!(manifest.iter_direct_dependencies().count(), 2);
let patches_count = package.path().join("patches")
.read_dir()?
.count();
assert_eq!(patches_count, 0);
Ok(())
})?;
Ok(())
}
fn skip_intro_patch() -> &'static str {
include_str!(
concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/dependencies/skip_intro_patch.patch"
)
)
}
#[test]
fn initialised_patches_maintained() -> Result<()> {
pretty_env_logger::init();
let tempdir = TempDir::new()?;
let package = Package::new("Package", tempdir.path().join("package"))?;
let patch_path = package.path().join("patches/0001-set-bSkipIntro-to-true.patch");
assert!(!patch_path.is_file());
let mut file = File::create(&patch_path)?;
write!(&mut file, "{}", skip_intro_patch())?;
assert!(patch_path.is_file());
let initialised = package.to_initialised(InitialiseOptions {
baserom: rom::baserom(),
rev: Some(DECOMP_REV.to_string()),
})?;
assert!(patch_path.is_file());
let output = Command::new("git")
.arg("rev-parse")
.arg("--abbrev-ref")
.arg("HEAD")
.current_dir(initialised.subrepo_path())
.output()?;
let branch = String::from_utf8(output.stdout)?.trim().to_string();
assert_eq!(branch, initialised.package_id().to_string());
initialised.update_decomp()?; assert!(patch_path.is_file());
initialised.setup_git_branches()?;
assert!(patch_path.is_file());
let output = Command::new("git")
.arg("log")
.arg("-1")
.arg("--pretty=format:%s")
.current_dir(initialised.subrepo_path())
.output()?;
let head_commit = String::from_utf8(output.stdout)?.trim().to_string();
assert_eq!(&head_commit, "set bSkipIntro to true");
Ok(())
}