mirror of
https://github.com/danbulant/lucide
synced 2026-06-17 13:31:24 +00:00
139 lines
3.7 KiB
Rust
139 lines
3.7 KiB
Rust
use std::{env, error::Error, path::Path};
|
|
|
|
use git2::{BranchType, Cred, IndexAddOption, PushOptions, RemoteCallbacks, Repository, Signature};
|
|
use log::info;
|
|
use semver::Version;
|
|
|
|
use crate::{GITHUB_OWNER, GITHUB_REPO, UPSTREAM_GIT_URL};
|
|
|
|
pub fn git_checkout<P: AsRef<Path>>(
|
|
path: P,
|
|
url: &str,
|
|
r#ref: &str,
|
|
) -> Result<Repository, Box<dyn Error>> {
|
|
info!(
|
|
"Cloning \"{}\" ref \"{}\" into \"{}\".",
|
|
UPSTREAM_GIT_URL,
|
|
r#ref,
|
|
path.as_ref().display()
|
|
);
|
|
|
|
let repository = Repository::clone(url, path)?;
|
|
|
|
{
|
|
let (object, reference) = repository.revparse_ext(r#ref)?;
|
|
|
|
repository.checkout_tree(&object, None)?;
|
|
|
|
match reference {
|
|
Some(reference) => {
|
|
repository.set_head(reference.name().expect("Reference name should exist."))?
|
|
}
|
|
None => repository.set_head_detached(object.id())?,
|
|
}
|
|
}
|
|
|
|
Ok(repository)
|
|
}
|
|
|
|
pub fn git_version_tags(repository: &Repository) -> Result<Vec<Version>, Box<dyn Error>> {
|
|
let tag_names = repository.tag_names(None)?;
|
|
let mut tag_names = tag_names
|
|
.into_iter()
|
|
.flat_map(|tag_name| {
|
|
tag_name.and_then(|tag_name| Version::parse(tag_name.trim_start_matches("v")).ok())
|
|
})
|
|
.collect::<Vec<_>>();
|
|
|
|
tag_names.sort();
|
|
|
|
Ok(tag_names)
|
|
}
|
|
|
|
pub fn git_has_remote_branch(repository: &Repository, branch_name: &str) -> bool {
|
|
repository
|
|
.find_branch(&format!("origin/{branch_name}"), BranchType::Remote)
|
|
.is_ok()
|
|
}
|
|
|
|
pub fn git_create_branch(repository: &Repository, branch_name: &str) -> Result<(), Box<dyn Error>> {
|
|
info!("Creating branch {branch_name}.");
|
|
|
|
let branch = repository.branch(branch_name, &repository.head()?.peel_to_commit()?, false)?;
|
|
|
|
repository.set_head(
|
|
branch
|
|
.into_reference()
|
|
.name()
|
|
.expect("Reference name should exist."),
|
|
)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn git_commit(repository: &Repository, message: &str) -> Result<(), Box<dyn Error>> {
|
|
info!("Committing.");
|
|
|
|
repository
|
|
.index()?
|
|
.add_all(["."], IndexAddOption::DEFAULT, None)?;
|
|
repository.index()?.write()?;
|
|
|
|
let signature = Signature::now(&env::var("GIT_USER_NAME")?, &env::var("GIT_USER_EMAIL")?)?;
|
|
let tree = repository.find_tree(repository.index()?.write_tree()?)?;
|
|
let parent = repository.head()?.peel_to_commit()?;
|
|
|
|
repository.commit(
|
|
Some("HEAD"),
|
|
&signature,
|
|
&signature,
|
|
message,
|
|
&tree,
|
|
&[&parent],
|
|
)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn git_push(repository: &Repository, branch_name: &str) -> Result<(), Box<dyn Error>> {
|
|
info!("Pushing branch {branch_name}.");
|
|
|
|
let branch = repository.find_branch(branch_name, BranchType::Local)?;
|
|
let branch_reference = branch.into_reference();
|
|
let branch_ref = branch_reference
|
|
.name()
|
|
.expect("Reference name should exist.");
|
|
|
|
let username = env::var("GITHUB_ACTOR")?;
|
|
let password = env::var("GITHUB_TOKEN")?;
|
|
|
|
let mut callbacks = RemoteCallbacks::new();
|
|
callbacks.credentials(|_, _, _| Cred::userpass_plaintext(&username, &password));
|
|
|
|
let mut options = PushOptions::new();
|
|
options.remote_callbacks(callbacks);
|
|
|
|
let mut remote = repository.find_remote("origin")?;
|
|
remote.push(&[branch_ref], Some(&mut options))?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn github_create_pull_request(
|
|
branch_name: &str,
|
|
title: &str,
|
|
body: &str,
|
|
) -> Result<(), Box<dyn Error>> {
|
|
let octocrab = octocrab::instance();
|
|
|
|
info!("Creating pull request for branch {branch_name}.");
|
|
|
|
octocrab
|
|
.pulls(GITHUB_OWNER, GITHUB_REPO)
|
|
.create(title, branch_name, "main")
|
|
.body(body)
|
|
.send()
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|