I've got an issue using Git2 lib for Rust. I'm trying to init a repository in a test with a specific state that could be recreated using theses commands:
git init
touch commit1.txt
git add commit1.txt
git commit -m "First Commit"
git checkout -b "ft/feature"
touch commit2.txt
git add commit2.txt
git commit -m "Second Commit"
To do that, I first init the repository using a temporary directory, then I pass the path to the temporary directory in the function that I'd like to test. In the function, after reopening the repository, I do have an issue where "commit2.txt" reappears in my statuses:
Status after initialization:
Path: C:/Users/mail/AppData/Local/Temp/.tmpuT5PaF/.git/
Active Branch:
Name: refs/heads/ft/my-new-feature
Last Commit ID: b6a3b9b8ab2347ad1a70a15a284c54275e31e062
Last Commit Message: Feature Commit
Repository Status: Clean
File statuses:
Branches:
Local:
refs/heads/ft/my-new-feature
refs/heads/main
Remote:
refs/remotes/origin/acceptance
refs/remotes/origin/develop
refs/remotes/origin/HEAD
refs/remotes/origin/main
Status after reload:
Path: C:/Users/mail/AppData/Local/Temp/.tmpuT5PaF/.git/
Active Branch:
Name: refs/heads/ft/my-new-feature
Last Commit ID: b6a3b9b8ab2347ad1a70a15a284c54275e31e062
Last Commit Message: Feature Commit
Repository Status: Clean
File statuses:
commit2.txt: Status(INDEX_DELETED | WT_NEW)
Branches:
Local:
refs/heads/ft/my-new-feature
refs/heads/main
Remote:
refs/remotes/origin/acceptance
refs/remotes/origin/develop
refs/remotes/origin/HEAD
refs/remotes/origin/main
Here is the initialization code:
fn init_remote_repository(path: &Path) -> Repository {
let repo = Repository::init(path).unwrap();
let new_file_name = "commit1.txt";
let mut f = File::create(path.join(new_file_name)).unwrap();
f.write_all(b"First commit").unwrap();
{
commit(&repo, "Initial Commit", vec![new_file_name]);
}
repo
}
fn init_local_repository(path: &Path, remote_repo: &Repository) -> Repository {
let repo = Repository::clone(remote_repo.path().to_str().unwrap(), path).unwrap();
let feature_branch_name = "ft/my-new-feature";
let feature_branch_reference_name = format!("refs/heads/{}", feature_branch_name);
let commit_id = repo.head().unwrap().target().unwrap();
{
let last_active_commit = repo.find_commit(commit_id).unwrap();
repo.branch(feature_branch_name, &last_active_commit, false)
.unwrap();
repositories::checkout(&repo, &feature_branch_reference_name).unwrap();
let new_file_name = "commit2.txt";
let mut f = File::create(path.join(new_file_name)).unwrap();
f.write_all(b"Second commit").unwrap();
commit(&repo, "Feature Commit", vec![new_file_name]);
}
repo
}
pub fn get_last_active_commit(repo: &Repository) -> Commit {
let reference = repo.head().unwrap();
let commit_id = reference.target().unwrap();
repo.find_commit(commit_id).unwrap()
}
pub fn commit<'a>(repo: &'a Repository, msg: &str, paths_to_add: Vec<&str>) -> Commit<'a> {
let signature = Signature::now("testuser", "test@fakemail.com").unwrap();
let mut index = repo.index().unwrap();
for path in paths_to_add {
index.add_path(Path::new(path)).unwrap();
}
let tree_id = index.write_tree().unwrap();
let commit = match repo.head() {
Ok(reference) => {
let commit_id = reference.target().unwrap();
let commit = repo.find_commit(commit_id).unwrap();
Some(commit)
}
Err(_) => None,
};
let parents_commit = match commit.as_ref() {
None => {
vec![]
}
Some(c) => {
vec![c]
}
};
let tree = repo.find_tree(tree_id).unwrap();
let last_commit_id = repo
.commit(
Some("HEAD"),
&signature,
&signature,
msg,
&tree,
&parents_commit,
)
.unwrap();
repositories::print_status("Local-Commit-AfterCommit", &repo);
let commit = repo.find_commit(last_commit_id).unwrap();
commit
}
Here is the code with the call to the the function to be tested:
repositories::merge(local_dir.path()).unwrap();
where local_dir is the directory used to initialize the repo. And here is the internal of
pub fn ulis3_merge(path: &Path) -> Result<(), Errors> {
let repo = match Repository::open(path) {
Ok(repo) => { repo }
Err(e) => {
return Err(Errors::CouldNotOpenRepository {
path: path.to_str().unwrap_or("").to_string(),
source: e,
});
}
};
let branch_name = current_branch_name(&repo)?;
merge_and_push(&repo, &branch_name, "develop")?;
}
I'm not sure what I'm doing wrong :(
The problem was in my commit function, I needed to add index.write().unwrap();
after adding the files to the index:
pub fn commit<'a>(repo: &'a Repository, msg: &str, paths_to_add: Vec<&str>) -> Commit<'a> {
let signature = Signature::now("testuser", "test@fakemail.com").unwrap();
let mut index = repo.index().unwrap();
for path in paths_to_add {
index.add_path(Path::new(path)).unwrap();
}
index.write().unwrap();
let tree_id = index.write_tree().unwrap();
let commit = match repo.head() {
Ok(reference) => {
let commit_id = reference.target().unwrap();
let commit = repo.find_commit(commit_id).unwrap();
Some(commit)
}
Err(_) => None,
};
let parents_commit = match commit.as_ref() {
None => {
vec![]
}
Some(c) => {
vec![c]
}
};
let tree = repo.find_tree(tree_id).unwrap();
let last_commit_id = repo
.commit(
Some("HEAD"),
&signature,
&signature,
msg,
&tree,
&parents_commit,
)
.unwrap();
repositories::print_status("Local-Commit-AfterCommit", &repo);
let commit = repo.find_commit(last_commit_id).unwrap();
commit
}