I'm building an app which internally uses git2.rs to manage a project.
I'm trying to implement tests for basic use cases such as git init, git add, commit and push to a remote and I have problems with the pushing part.
I implemented my test case using a local bare remote repository. I first create a source repository, init git inside of it, then I create a dumb text file, add it to the index and commit it.
Everything seems to work until there.
Then I create a local bare repo, I set it as the "origin" remote for the source repo and I call push on the remote repo instance. I have no errors but the content of the source repo doesn't seems to be pushed.
The documentation is not very learner friendly so I have troubles understanding what I'm doing.
I would expect maybe to see my text file somewhere is the remote repo directory but there is only the git structure.
And when I try to make an assertion by cloning the remote into a new directoryy after pushing I check if the text file is there, but it's not, it just creates an empty repository.
Here is the relevant part of my code, it's just a trait which I implement in the tests submodule.
The source trait
use git2::Repository;
use std::path::PathBuf;
pub trait Git {
// ... other methods...
fn _set_remote<'a, T: Into<PathBuf>>(
repo_dir: T,
name: &str,
url: &str,
) -> Result<(), git2::Error> {
let repo = Self::_repo(repo_dir)?;
repo.remote(name, url)?;
Ok(())
}
fn git_init(&self) -> Result<Repository, git2::Error>;
fn git_add<'a, E: Into<&'a str>>(&self, expr: E) -> Result<git2::Index, git2::Error>;
fn git_commit<'a, M: Into<&'a str>>(&self, message: M) -> Result<git2::Oid, git2::Error>;
fn git_set_remote(&self, name: &str, url: &str) -> Result<(), git2::Error>;
}
The tests implementation
#[cfg(test)]
mod tests {
use super::*;
use std::io::Write;
struct TestGit {
pub dir: PathBuf,
pub state: String,
}
// Impl TestGit ...
impl Git for TestGit {
fn git_init(&self) -> Result<Repository, git2::Error> {
// ...
}
fn git_add<'a, E: Into<&'a str>>(&self, expr: E) -> Result<git2::Index, git2::Error> {
// ...
}
fn git_commit<'a, M: Into<&'a str>>(&self, message: M) -> Result<git2::Oid, git2::Error> {
// ...
}
fn git_set_remote(&self, name: &str, url: &str) -> Result<(), git2::Error> {
Self::_set_remote(&self.dir, name, url)
}
}
// Some first tests for init, add, commit, write file, etc.
// ...
#[test]
fn test_push() {
let testgit = TestGit {
dir: std::env::current_dir().unwrap().join("test/base"),
state: String::from("Hello"),
};
let base_repo = testgit.git_init().unwrap();
let testgitremote = create_testgit_instance("test/remote");
<TestGit as Git>::_init::<&PathBuf>(&testgitremote.dir, true).unwrap();
testgit
.git_set_remote(
"origin",
format!("file://{}", testgitremote.dir.to_str().unwrap()).as_str(),
)
.unwrap();
testgit.write_file("test.txt").unwrap(); // This creates a test.txt file with "Hello" in it at the root of the repo.
testgit.git_add(".").unwrap();
testgit.git_commit("test commit").unwrap();
// This works find until there becauses I tested it elsewhere, the index contains one more element after the commit.
let mut remote = base_repo.find_remote("origin").unwrap();
remote.push::<&str>(&[], None).unwrap(); // This is what I'm having troubles to understand, I'm guessing I'm just pushing nothing but I don't find anything clear in the docs and there is no "push" example it the git2.rs sources.
let mut clonebuilder = git2::build::RepoBuilder::new();
let clonerepo_dir = testgit.dir.parent().unwrap().join("clone");
clonebuilder
.clone(remote.url().unwrap(), &clonerepo_dir)
.unwrap();
assert!(clonerepo_dir.join("test.txt").exists()); // This fails...
std::fs::remove_dir_all(&testgit.dir.parent().unwrap()).unwrap();
}
}
I also tried to add refspecs like this but it doesn't changed anything
let mut remote = base_repo.find_remote("origin").unwrap();
remote.push::<&str>(&["refs/heads/master:refs/heads/master")], None).unwrap();
Or like this, same result.
let mut remote = base_repo.find_remote("origin").unwrap();
base_repo
.remote_add_push("origin", "refs/heads/master:refs/heads/master")
.unwrap();
remote.push::<&str>(&[], None).unwrap();
Thank you very much for any help.
I got an solution in this thread https://users.rust-lang.org/t/how-to-use-git2-push-correctly/97202/6 , I rely it here in case it could be useful.
It turned out the problem was from my
git commitimplementation. I forgot to update the branch pointer with the new commit. That's why nothing was pushed.This is the snippet that gave me the solution
If useful, here is my fixed implementation of add and commit, and the push test.