use code2prompt_core::git::{get_git_diff, get_git_diff_between_branches, get_git_log};
#[cfg(test)]
mod tests {
use super::*;
use git2::{Repository, RepositoryInitOptions, Signature};
use std::fs;
use tempfile::TempDir;
#[test]
fn test_get_git_diff() {
// Create a temporary directory
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let repo_path = temp_dir.path();
// Initialize a new Git repository
let repo = Repository::init(repo_path).expect("Failed to initialize repository");
// Create a new file in the repository
let file_path = repo_path.join("test_file.txt");
fs::write(&file_path, "Initial content").expect("Failed to write to test file");
// Stage and commit the new file
let mut index = repo.index().expect("Failed to get repository index");
index
.add_path(file_path.strip_prefix(repo_path).unwrap())
.expect("Failed to add file to index");
index.write().expect("Failed to write index");
let tree_id = index.write_tree().expect("Failed to write tree");
let tree = repo.find_tree(tree_id).expect("Failed to find tree");
let signature =
Signature::now("Test", "test@example.com").expect("Failed to create signature");
repo.commit(
Some("HEAD"),
&signature,
&signature,
"Initial commit",
&tree,
&[],
)
.expect("Failed to commit");
// Modify the file
fs::write(&file_path, "Modified content").expect("Failed to modify test file");
// Add the modified file to the index again
let mut index = repo.index().expect("Failed to get repository index");
index
.add_path(file_path.strip_prefix(repo_path).unwrap())
.expect("Failed to add file to index");
index.write().expect("Failed to write index");
// Get the git diff using the function from the module
let diff = get_git_diff(repo_path).expect("Failed to get git diff");
// Print the diff for debugging
println!("Generated diff:\n{}", diff);
// Assert that the diff contains the expected content
assert!(diff.contains("Modified content"));
}
#[test]
fn test_get_git_diff_between_branches() {
// Create a temporary directory
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let repo_path = temp_dir.path();
// Initialize a new Git repository
let mut binding = RepositoryInitOptions::new();
let init_options = binding.initial_head("master");
let repo = Repository::init_opts(repo_path, init_options)
.expect("Failed to initialize repository");
// Create a new file in the repository
let file_path = repo_path.join("test_file.txt");
fs::write(&file_path, "Initial content").expect("Failed to write to test file");
// Stage and commit the new file
let mut index = repo.index().expect("Failed to get repository index");
index
.add_path(file_path.strip_prefix(repo_path).unwrap())
.expect("Failed to add file to index");
index.write().expect("Failed to write index");
let tree_id = index.write_tree().expect("Failed to write tree");
let tree = repo.find_tree(tree_id).expect("Failed to find tree");
let signature =
Signature::now("Test", "test@example.com").expect("Failed to create signature");
let master_commit = repo
.commit(
Some("HEAD"),
&signature,
&signature,
"Initial commit in master branch",
&tree,
&[],
)
.expect("Failed to commit");
// Create a new branch and make a commit on the master branch
repo.branch(
"development",
&repo
.find_commit(master_commit)
.expect("Failed to find commit"),
false,
)
.expect("Failed to create new branch");
// Modify the file in the new branch
repo.set_head("refs/heads/development")
.expect("Failed to set HEAD");
repo.checkout_head(None).expect("Failed to checkout HEAD");
fs::write(&file_path, "Content in new branch")
.expect("Failed to modify test file in new branch");
let mut index = repo.index().expect("Failed to get repository index");
index
.add_path(file_path.strip_prefix(repo_path).unwrap())
.expect("Failed to add file to index");
index.write().expect("Failed to write index");
let tree_id = index.write_tree().expect("Failed to write tree");
let tree = repo.find_tree(tree_id).expect("Failed to find tree");
repo.commit(
Some("HEAD"),
&signature,
&signature,
"New commit in branch development",
&tree,
&[&repo
.find_commit(master_commit)
.expect("Failed to find commit")],
)
.expect("Failed to commit in new branch");
// Get the git diff between branches
let diff = get_git_diff_between_branches(repo_path, "master", "development")
.expect("Failed to get git diff between branches");
// Print the diff for debugging
println!("Generated diff between branches:\n{}", diff);
// Assert that the diff contains the expected content
assert!(diff.contains("Initial content"));
assert!(diff.contains("Content in new branch"));
}
#[test]
fn test_get_git_log() {
// Create a temporary directory
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let repo_path = temp_dir.path();
// Initialize a new Git repository
let mut binding = RepositoryInitOptions::new();
let init_options = binding.initial_head("master");
let repo = Repository::init_opts(repo_path, init_options)
.expect("Failed to initialize repository");
// Create a new file in the repository
let file_path = repo_path.join("test_file.txt");
fs::write(&file_path, "Initial content").expect("Failed to write to test file");
// Stage and commit the new file
let mut index = repo.index().expect("Failed to get repository index");
index
.add_path(file_path.strip_prefix(repo_path).unwrap())
.expect("Failed to add file to index");
index.write().expect("Failed to write index");
let tree_id = index.write_tree().expect("Failed to write tree");
let tree = repo.find_tree(tree_id).expect("Failed to find tree");
let signature =
Signature::now("Test", "test@example.com").expect("Failed to create signature");
let master_commit = repo
.commit(
Some("HEAD"),
&signature,
&signature,
"Initial commit in branch master",
&tree,
&[],
)
.expect("Failed to commit");
// Create a new branch and make a commit on the master branch
repo.branch(
"development",
&repo
.find_commit(master_commit)
.expect("Failed to find commit"),
false,
)
.expect("Failed to create new branch");
// Modify the file in the new branch
repo.set_head("refs/heads/development")
.expect("Failed to set HEAD");
repo.checkout_head(None).expect("Failed to checkout HEAD");
fs::write(&file_path, "Content in development")
.expect("Failed to modify test file in new branch");
let mut index = repo.index().expect("Failed to get repository index");
index
.add_path(file_path.strip_prefix(repo_path).unwrap())
.expect("Failed to add file to index");
index.write().expect("Failed to write index");
let tree_id = index.write_tree().expect("Failed to write tree");
let tree = repo.find_tree(tree_id).expect("Failed to find tree");
repo.commit(
Some("HEAD"),
&signature,
&signature,
"First commit in development",
&tree,
&[&repo
.find_commit(master_commit)
.expect("Failed to find commit")],
)
.expect("Failed to commit in new branch");
// Make a second commit in the development branch
fs::write(&file_path, "Second content in development")
.expect("Failed to modify test file in new branch");
let mut index = repo.index().expect("Failed to get repository index");
index
.add_path(file_path.strip_prefix(repo_path).unwrap())
.expect("Failed to add file to index");
index.write().expect("Failed to write index");
let tree_id = index.write_tree().expect("Failed to write tree");
let tree = repo.find_tree(tree_id).expect("Failed to find tree");
repo.commit(
Some("HEAD"),
&signature,
&signature,
"Second commit in development",
&tree,
&[&repo
.find_commit(repo.head().unwrap().target().unwrap())
.expect("Failed to find commit")],
)
.expect("Failed to commit second change in new branch");
// Get the git log between branches
let log = get_git_log(repo_path, "master", "development")
.expect("Failed to get git log between branches");
// Print the log for debugging
println!("Generated git log:\n{}", log);
// Assert that the log contains the expected content
assert!(log.contains("First commit in development"));
assert!(log.contains("Second commit in development"));
}
#[test]
fn test_git_diff_with_commit_hashes_and_tags() {
// Create a temporary directory
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let repo_path = temp_dir.path();
// Initialize a new Git repository
let mut binding = RepositoryInitOptions::new();
let init_options = binding.initial_head("master");
let repo = Repository::init_opts(repo_path, init_options)
.expect("Failed to initialize repository");
// Create a new file in the repository
let file_path = repo_path.join("test_file.txt");
fs::write(&file_path, "Initial content").expect("Failed to write to test file");
// Stage and commit the new file
let mut index = repo.index().expect("Failed to get repository index");
index
.add_path(file_path.strip_prefix(repo_path).unwrap())
.expect("Failed to add file to index");
index.write().expect("Failed to write index");
let tree_id = index.write_tree().expect("Failed to write tree");
let tree = repo.find_tree(tree_id).expect("Failed to find tree");
let signature =
Signature::now("Test", "test@example.com").expect("Failed to create signature");
let first_commit_id = repo
.commit(
Some("HEAD"),
&signature,
&signature,
"First commit",
&tree,
&[],
)
.expect("Failed to commit");
// Create a tag for the first commit
let first_commit = repo
.find_commit(first_commit_id)
.expect("Failed to find first commit");
repo.tag(
"v1.0.0",
first_commit.as_object(),
&signature,
"Version 1.0.0",
false,
)
.expect("Failed to create tag");
// Make a second commit
fs::write(&file_path, "Modified content").expect("Failed to modify test file");
let mut index = repo.index().expect("Failed to get repository index");
index
.add_path(file_path.strip_prefix(repo_path).unwrap())
.expect("Failed to add file to index");
index.write().expect("Failed to write index");
let tree_id = index.write_tree().expect("Failed to write tree");
let tree = repo.find_tree(tree_id).expect("Failed to find tree");
let second_commit_id = repo
.commit(
Some("HEAD"),
&signature,
&signature,
"Second commit",
&tree,
&[&first_commit],
)
.expect("Failed to commit second change");
// Test 1: Diff between commit hashes (full hash)
let first_commit_hash = first_commit_id.to_string();
let second_commit_hash = second_commit_id.to_string();
let diff_full_hash =
get_git_diff_between_branches(repo_path, &first_commit_hash, &second_commit_hash)
.expect("Failed to get git diff between full commit hashes");
assert!(diff_full_hash.contains("Initial content"));
assert!(diff_full_hash.contains("Modified content"));
// Test 2: Diff between abbreviated commit hashes
let first_commit_short = &first_commit_hash[..7];
let second_commit_short = &second_commit_hash[..7];
let diff_short_hash =
get_git_diff_between_branches(repo_path, first_commit_short, second_commit_short)
.expect("Failed to get git diff between abbreviated commit hashes");
assert!(diff_short_hash.contains("Initial content"));
assert!(diff_short_hash.contains("Modified content"));
// Test 3: Diff between tag and commit hash
let diff_tag_to_hash =
get_git_diff_between_branches(repo_path, "v1.0.0", &second_commit_hash)
.expect("Failed to get git diff between tag and commit hash");
assert!(diff_tag_to_hash.contains("Initial content"));
assert!(diff_tag_to_hash.contains("Modified content"));
// Test 4: Diff between tag and HEAD
let diff_tag_to_head = get_git_diff_between_branches(repo_path, "v1.0.0", "HEAD")
.expect("Failed to get git diff between tag and HEAD");
assert!(diff_tag_to_head.contains("Initial content"));
assert!(diff_tag_to_head.contains("Modified content"));
// Test 5: Error case - invalid reference should still fail
let result = get_git_diff_between_branches(repo_path, "nonexistent_reference", "HEAD");
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("Branch nonexistent_reference doesn't exist!"));
}
}