use heroforge_core::{Repository, Result};
use std::fs;
use std::path::Path;
use std::process::Command;
fn run_fossil(args: &[&str], cwd: &Path) -> std::result::Result<String, String> {
let output = Command::new("heroforge")
.args(args)
.current_dir(cwd)
.output()
.map_err(|e| format!("Failed to run heroforge: {}", e))?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
return Err(format!("Heroforge command failed: {}", stderr));
}
Ok(String::from_utf8_lossy(&output.stdout).to_string())
}
fn main() -> Result<()> {
let test_dir = Path::new("/tmp/heroforge_write_test");
let repo_file = test_dir.join("test.forge");
if test_dir.exists() {
fs::remove_dir_all(test_dir).expect("Failed to clean up test directory");
}
fs::create_dir_all(test_dir).expect("Failed to create test directory");
println!("=== Creating Repository with heroforge ===\n");
let repo = Repository::init(&repo_file)?;
println!("Created repository: {}", repo_file.display());
let initial_hash = repo
.commit_builder()
.message("initial empty check-in")
.author("testuser")
.initial()
.execute()?;
println!("Initial check-in: {}", &initial_hash[..16]);
let mut version_hashes: Vec<String> = Vec::new();
let mut version_contents: Vec<String> = Vec::new();
println!("\n=== Writing 10 Versions with heroforge ===\n");
let mut parent_hash = initial_hash;
for i in 1..=10 {
let content = format!(
"Version {} of test file\n\
Created at iteration {}\n\
Some data: {}\n\
More lines to make it interesting:\n\
- Line A for version {}\n\
- Line B for version {}\n\
- Line C for version {}\n",
i,
i,
i * 100,
i,
i,
i
);
version_contents.push(content.clone());
let commit_hash = repo
.commit_builder()
.message(&format!("Commit version {}", i))
.author("testuser")
.parent(&parent_hash)
.branch("trunk")
.file("testfile.txt", content.as_bytes())
.execute()?;
version_hashes.push(commit_hash.clone());
println!("Version {}: committed as [{}]", i, &commit_hash[..16]);
parent_hash = commit_hash;
}
println!("\n=== Reading Versions via heroforge ===\n");
let mut rs_match_count = 0;
for (i, hash) in version_hashes.iter().enumerate() {
let version_num = i + 1;
let expected_content = &version_contents[i];
match repo.files().at_commit(hash).read_string("testfile.txt") {
Ok(content_str) => {
if content_str.trim() == expected_content.trim() {
println!("Version {}: heroforge read OK", version_num);
rs_match_count += 1;
} else {
println!("Version {}: heroforge MISMATCH", version_num);
println!(
" Expected: {:?}...",
&expected_content[..50.min(expected_content.len())]
);
println!(
" Got: {:?}...",
&content_str[..50.min(content_str.len())]
);
}
}
Err(e) => {
println!("Version {}: heroforge read ERROR: {}", version_num, e);
}
}
}
println!("\n=== Verifying with Heroforge CLI ===\n");
let work_dir = test_dir.join("work");
fs::create_dir_all(&work_dir).expect("Failed to create work directory");
match run_fossil(&["open", repo_file.to_str().unwrap()], &work_dir) {
Ok(_) => println!("Heroforge CLI opened repository successfully"),
Err(e) => {
println!("Heroforge CLI failed to open: {}", e);
println!("\nNote: The repository was created with heroforge.");
println!("If heroforge CLI fails, the format may need adjustment.");
}
}
match run_fossil(&["timeline", "-n", "15", "-t", "ci"], &work_dir) {
Ok(timeline) => {
println!("\nFossil CLI timeline:");
for line in timeline.lines().take(15) {
println!(" {}", line);
}
}
Err(e) => println!("Could not get timeline: {}", e),
}
println!("\n=== CLI Content Verification ===\n");
let mut cli_match_count = 0;
let repo_path = repo_file.to_str().unwrap();
for (i, hash) in version_hashes.iter().enumerate() {
let version_num = i + 1;
let expected_content = &version_contents[i];
let short_hash = &hash[..16];
match run_fossil(
&["cat", "testfile.txt", "-r", short_hash, "-R", repo_path],
test_dir,
) {
Ok(cli_content) => {
if cli_content.trim() == expected_content.trim() {
println!("Version {}: CLI verification OK", version_num);
cli_match_count += 1;
} else {
println!("Version {}: CLI MISMATCH", version_num);
}
}
Err(e) => {
println!("Version {}: CLI read failed: {}", version_num, e);
}
}
}
println!("\n=== Summary ===\n");
println!("heroforge read: {}/10 versions matched", rs_match_count);
println!(
"heroforge CLI read: {}/10 versions matched",
cli_match_count
);
if rs_match_count == 10 && cli_match_count == 10 {
println!("\nSUCCESS: All versions match in both heroforge and heroforge CLI!");
} else if rs_match_count == 10 {
println!("\nPARTIAL: heroforge works, CLI may need format adjustments");
} else {
println!("\nFAILED: Some versions could not be read");
}
println!("\nVersion hash mapping:");
for (i, hash) in version_hashes.iter().enumerate() {
println!(" Version {}: {}", i + 1, &hash[..32]);
}
Ok(())
}