use git2::Error;
use std::path::Path;
use url::Url;
pub struct Repository {
repo: git2::Repository,
}
pub(crate) struct Identity<'a> {
pub username: &'a str,
pub email: &'a str,
}
impl Repository {
pub fn init(root: impl AsRef<Path>) -> Result<Self, Error> {
let repo = git2::Repository::init(root)?;
Ok(Repository { repo })
}
pub fn create_initial_commit(&self) -> Result<(), Error> {
let signature = self.repo.signature()?;
let oid = self.repo.index()?.write_tree()?;
let tree = self.repo.find_tree(oid)?;
self.repo.commit(
Some("HEAD"),
&signature,
&signature,
"Initial commit",
&tree,
&[],
)?;
Ok(())
}
pub fn open(root: impl AsRef<Path>) -> Result<Self, Error> {
let repo = git2::Repository::open(root)?;
Ok(Repository { repo })
}
pub(crate) fn add_origin(&self, remote: &Url) -> Result<(), Error> {
self.repo.remote("origin", remote.as_str())?;
Ok(())
}
pub(crate) fn set_username(&self, username: impl AsRef<str>) -> Result<(), Error> {
self.repo.config()?.set_str("user.name", username.as_ref())
}
pub(crate) fn set_email(&self, email: impl AsRef<str>) -> Result<(), Error> {
self.repo.config()?.set_str("user.email", email.as_ref())
}
pub fn add_path(&self, path: impl AsRef<Path>) -> Result<(), Error> {
self.repo.index()?.add_path(path.as_ref())
}
pub fn add_all(&self) -> Result<(), Error> {
self.repo
.index()?
.add_all(&["*"], git2::IndexAddOption::DEFAULT, None)
}
fn find_last_commit(&self) -> Result<git2::Commit, Error> {
self.repo.head()?.peel_to_commit()
}
pub fn commit(&self, message: impl AsRef<str>) -> Result<(), Error> {
let mut index = self.repo.index()?;
let oid = index.write_tree()?;
let signature = self.repo.signature()?;
let parent_commit = self.find_last_commit()?;
let tree = self.repo.find_tree(oid)?;
self.repo.commit(
Some("HEAD"),
&signature,
&signature,
message.as_ref(),
&tree,
&[&parent_commit],
)?;
Ok(())
}
pub fn push(&self) -> Result<(), Error> {
let refspecs: Vec<String> = Vec::new();
for remote_name in self.repo.remotes()?.into_iter().filter_map(|x| x) {
self.repo.find_remote(&remote_name)?.push(&refspecs, None)?;
}
Ok(())
}
}