support pulling, refactor git module

This commit is contained in:
Cadey Ratio 2020-07-09 11:31:09 -04:00
parent 2c098d4f23
commit bc608f7ddc
3 changed files with 96 additions and 22 deletions

View File

@ -11,10 +11,11 @@ pub(crate) async fn run(
let repo = git2::Repository::open(".")?; let repo = git2::Repository::open(".")?;
let tag = tag.unwrap_or(version::read_version("VERSION".into())?); let tag = tag.unwrap_or(version::read_version("VERSION".into())?);
let desc = changelog::read(fname.clone(), tag.clone())?; let desc = changelog::read(fname.clone(), tag.clone())?;
let sig = git2::Signature::now(&common.username, &common.email)?;
if !git::has_tag(&repo, tag.clone())? { if !git::has_tag(&repo, tag.clone())? {
git::tag_version(&repo, tag.clone(), desc.clone())?; git::tag_version(&repo, tag.clone(), desc.clone(), &sig)?;
let _ = git::push_tags(&repo); let _ = git::push(&repo, common.token.clone(), git::TAGS);
} else } else
/* The tag already exists */ /* The tag already exists */
{ {

View File

@ -9,18 +9,30 @@ pub(crate) struct Common {
/// The gitea server to connect to /// The gitea server to connect to
#[structopt(short, long, env = "GITEA_SERVER")] #[structopt(short, long, env = "GITEA_SERVER")]
pub server: String, pub server: String,
/// The gitea token to authenticate with /// The gitea token to authenticate with
#[structopt(long, env = "GITEA_TOKEN")] #[structopt(long, env = "GITEA_TOKEN")]
pub token: String, pub token: String,
/// The gitea user to authenticate as /// The gitea user to authenticate as
#[structopt(short, long, env = "GITEA_AUTH_USER")] #[structopt(short, long, env = "GITEA_AUTH_USER")]
pub auth_user: String, pub auth_user: String,
/// The owner of the gitea repo /// The owner of the gitea repo
#[structopt(short, long, env = "GITEA_OWNER")] #[structopt(short, long, env = "GITEA_OWNER")]
pub owner: String, pub owner: String,
/// The gitea repo to operate on /// The gitea repo to operate on
#[structopt(short, long, env = "GITEA_REPO")] #[structopt(short, long, env = "GITEA_REPO")]
pub repo: String, pub repo: String,
/// Git signature email
#[structopt(long, short = "E", env = "SIGNATURE_EMAIL", default_value = "domo@tulpa.dev")]
pub email: String,
/// Git signature username
#[structopt(long, short = "U", env = "SIGNATURE_NAME", default_value = "Domo Arigato")]
pub username: String,
} }
#[derive(StructOpt, Debug, Clone)] #[derive(StructOpt, Debug, Clone)]
@ -29,12 +41,15 @@ pub(crate) struct DroneEnv {
/// push URL /// push URL
#[structopt(long, env = "DRONE_GIT_HTTP_URL")] #[structopt(long, env = "DRONE_GIT_HTTP_URL")]
pub push_url: String, pub push_url: String,
/// repo owner /// repo owner
#[structopt(long, env = "DRONE_REPO_OWNER")] #[structopt(long, env = "DRONE_REPO_OWNER")]
pub owner: String, pub owner: String,
/// repo name /// repo name
#[structopt(long, env = "DRONE_REPO_NAME")] #[structopt(long, env = "DRONE_REPO_NAME")]
pub repo: String, pub repo: String,
/// branch /// branch
#[structopt(long, env = "DRONE_REPO_BRANCH")] #[structopt(long, env = "DRONE_REPO_BRANCH")]
pub branch: String, pub branch: String,
@ -43,18 +58,30 @@ pub(crate) struct DroneEnv {
/// auth username /// auth username
#[structopt(long, env = "PLUGIN_AUTH_USERNAME")] #[structopt(long, env = "PLUGIN_AUTH_USERNAME")]
pub auth_user: String, pub auth_user: String,
/// Gitea server /// Gitea server
#[structopt(long, env = "PLUGIN_GITEA_SERVER")] #[structopt(long, env = "PLUGIN_GITEA_SERVER")]
pub server: String, pub server: String,
/// Gitea token /// Gitea token
#[structopt(long, env = "PLUGIN_GITEA_TOKEN")] #[structopt(long, env = "PLUGIN_GITEA_TOKEN")]
pub token: String, pub token: String,
/// CHANGELOG path /// CHANGELOG path
#[structopt(long, env = "PLUGIN_CHANGELOG_PATH", default_value = "./CHANGELOG.md")] #[structopt(long, env = "PLUGIN_CHANGELOG_PATH", default_value = "./CHANGELOG.md")]
pub changelog_path: PathBuf, pub changelog_path: PathBuf,
/// Default branch name /// Default branch name
#[structopt(long, env = "PLUGIN_DEFAULT_BRANCH")] #[structopt(long, env = "PLUGIN_DEFAULT_BRANCH")]
pub default_branch: Option<String>, pub default_branch: Option<String>,
/// Git signature email
#[structopt(long, short = "E", env = "PLUGIN_SIGNATURE_EMAIL", default_value = "domo@tulpa.dev")]
pub email: String,
/// Git signature username
#[structopt(long, short = "U", env = "PLUGIN_SIGNATURE_NAME", default_value = "Domo Arigato")]
pub username: String,
} }
impl Into<Common> for DroneEnv { impl Into<Common> for DroneEnv {
@ -65,6 +92,8 @@ impl Into<Common> for DroneEnv {
auth_user: self.auth_user, auth_user: self.auth_user,
owner: self.owner, owner: self.owner,
repo: self.repo, repo: self.repo,
email: self.email,
username: self.username,
} }
} }
} }

View File

@ -1,22 +1,77 @@
use anyhow::Result; use anyhow::Result;
use git2::{Repository, Signature}; use git2::{Repository, Signature};
use std::path::Path;
pub(crate) fn push_tags(repo: &Repository) -> Result<()> { 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 remote = repo.find_remote("origin")?;
remote.connect(git2::Direction::Push)?; let mut fo = git2::FetchOptions::new();
remote.push(&["refs/tags/*:refs/tags/*"], None)?;
let mut callbacks = git2::RemoteCallbacks::new();
callbacks.credentials(|_u, _username, allowed_types| {
if allowed_types.contains(git2::CredentialType::SSH_KEY) {
let user = "git";
git2::Cred::ssh_key_from_agent(user)
} else {
git2::Cred::userpass_plaintext(&token, "")
}
});
fo.remote_callbacks(callbacks);
remote.connect(git2::Direction::Fetch)?;
remote.fetch(what, Some(&mut fo), None)?;
Ok(()) Ok(())
} }
pub(crate) fn tag_version(repo: &Repository, tag: String, desc: String) -> Result<()> { pub fn push(repo: &Repository, token: String, what: &[&str]) -> Result<()> {
let sig = &Signature::now("Gitea Release Tool", "gitea-release@tulpa.dev")?; let mut remote = repo.find_remote("origin")?;
let mut po = git2::PushOptions::new();
let mut callbacks = git2::RemoteCallbacks::new();
callbacks.credentials(|_u, _username, allowed_types| {
if allowed_types.contains(git2::CredentialType::SSH_KEY) {
let user = "git";
git2::Cred::ssh_key_from_agent(user)
} else {
git2::Cred::userpass_plaintext(&token, "")
}
});
po.remote_callbacks(callbacks);
remote.connect(git2::Direction::Push)?;
remote.push(what, Some(&mut po))?;
Ok(())
}
pub fn commit(
repo: &Repository,
sig: &git2::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, tag: String, desc: String, sig: &git2::Signature) -> Result<()> {
let obj = repo.revparse_single("HEAD")?; let obj = repo.revparse_single("HEAD")?;
repo.tag(&tag, &obj, &sig, &desc, false)?; repo.tag(&tag, &obj, &sig, &desc, false)?;
Ok(()) Ok(())
} }
pub(crate) fn has_tag(repo: &Repository, tag: String) -> Result<bool> { pub fn has_tag(repo: &Repository, tag: String) -> Result<bool> {
let tags = repo.tag_names(Some(&tag))?; let tags = repo.tag_names(Some(&tag))?;
for tag_obj in tags.iter() { for tag_obj in tags.iter() {
@ -37,7 +92,7 @@ pub(crate) fn has_tag(repo: &Repository, tag: String) -> Result<bool> {
mod tests { mod tests {
use anyhow::Result; use anyhow::Result;
use git2::*; use git2::*;
use std::{fs::File, io::Write, path::Path}; use std::{fs::File, io::Write};
use tempfile::tempdir; use tempfile::tempdir;
#[test] #[test]
@ -48,22 +103,11 @@ mod tests {
let mut fout = File::create(&dir.path().join("VERSION"))?; let mut fout = File::create(&dir.path().join("VERSION"))?;
write!(fout, "{}", TAG)?; write!(fout, "{}", TAG)?;
drop(fout); drop(fout);
let mut index = repo.index()?;
index.add_path(Path::new("VERSION"))?;
let oid = index.write_tree()?;
let tree = repo.find_tree(oid)?;
let sig = &Signature::now("Gitea Release Tool", "gitea-release@tulpa.dev")?; let sig = &Signature::now("Gitea Release Tool", "gitea-release@tulpa.dev")?;
repo.commit( super::commit(&repo, &sig, "test commit please ignore", &["VERSION"])?;
Some("HEAD"),
&sig,
&sig,
"test commit please ignore",
&tree,
&[],
)?;
super::tag_version(&repo, TAG.into(), format!("version {}", TAG))?; super::tag_version(&repo, TAG.into(), format!("version {}", TAG), &sig)?;
assert!(super::has_tag(&repo, TAG.into())?); assert!(super::has_tag(&repo, TAG.into())?);
Ok(()) Ok(())