gitea-release/src/git.rs

106 lines
3.0 KiB
Rust

use anyhow::Result;
use git2::{
Cred, CredentialType, Direction, FetchOptions, PushOptions, RemoteCallbacks, Repository,
Signature,
};
use std::path::Path;
pub const TAGS: &'static [&'static str] = &["refs/tags/*:refs/tags/*"];
pub fn pull(repo: &Repository, token: String, what: &[&str]) -> Result<()> {
let mut remote = repo.find_remote("origin")?;
let mut fo = FetchOptions::new();
remote.connect_auth(Direction::Fetch, Some(callbacks(token.clone())), None)?;
fo.remote_callbacks(callbacks(token));
remote.fetch(what, Some(&mut fo), None)?;
Ok(())
}
fn callbacks<'a>(token: String) -> RemoteCallbacks<'a> {
let mut callbacks = RemoteCallbacks::new();
callbacks.credentials(move |_u, _username, allowed_types| {
if allowed_types.contains(CredentialType::SSH_KEY) {
let user = "git";
Cred::ssh_key_from_agent(user)
} else {
Cred::userpass_plaintext(&token, "x-oauth-basic")
}
});
callbacks
}
pub fn push(repo: &Repository, token: String, what: &[&str]) -> Result<()> {
let mut remote = repo.find_remote("origin")?;
remote.connect_auth(Direction::Push, Some(callbacks(token.clone())), None)?;
let mut po = PushOptions::new();
po.remote_callbacks(callbacks(token));
remote.push(what, Some(&mut po))?;
Ok(())
}
pub fn commit(repo: &Repository, sig: &Signature, msg: &str, files: &[&str]) -> Result<()> {
let mut index = repo.index()?;
for file in files {
index.add_path(Path::new(file))?;
}
let oid = index.write_tree()?;
let tree = repo.find_tree(oid)?;
repo.commit(Some("HEAD"), &sig, &sig, &msg, &tree, &[])?;
Ok(())
}
pub fn tag_version(repo: &Repository, sig: &Signature, tag: String, desc: String) -> Result<()> {
let obj = repo.revparse_single("HEAD")?;
repo.tag(&tag, &obj, &sig, &desc, false)?;
Ok(())
}
pub fn has_tag(repo: &Repository, tag: String) -> Result<bool> {
let tags = repo.tag_names(Some(&tag))?;
for tag_obj in tags.iter() {
if tag_obj.is_none() {
continue;
}
let tag_name = tag_obj.unwrap();
log::debug!("tag: {}", tag_name.to_string());
if tag == tag_name.to_string() {
return Ok(true);
}
}
Ok(false)
}
#[cfg(test)]
mod tests {
use anyhow::Result;
use git2::*;
use std::{fs::File, io::Write};
use tempfile::tempdir;
#[test]
fn has_tag() -> Result<()> {
const TAG: &'static str = "0.1.0";
let dir = tempdir()?;
let repo = Repository::init(&dir)?;
let mut fout = File::create(&dir.path().join("VERSION"))?;
write!(fout, "{}", TAG)?;
drop(fout);
let sig = &Signature::now("Gitea Release Tool", "gitea-release@tulpa.dev")?;
super::commit(&repo, &sig, "test commit please ignore", &["VERSION"])?;
super::tag_version(&repo, &sig, TAG.into(), format!("version {}", TAG))?;
assert!(super::has_tag(&repo, TAG.into())?);
Ok(())
}
}