crates/evaluator: add multi-branch evaluation support

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Ida40acb8d093f7d7e387913681b767276a6a6964
This commit is contained in:
raf 2026-02-02 01:24:44 +03:00
commit 00a4dc8d37
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
5 changed files with 62 additions and 39 deletions

View file

@ -3,8 +3,16 @@ use std::path::{Path, PathBuf};
use fc_common::error::Result;
use git2::Repository;
/// Clone or fetch a repository. Returns (repo_path, head_commit_hash).
pub fn clone_or_fetch(url: &str, work_dir: &Path, project_name: &str) -> Result<(PathBuf, String)> {
/// Clone or fetch a repository. Returns (repo_path, commit_hash).
///
/// If `branch` is `Some`, resolve `refs/remotes/origin/<branch>` instead of HEAD.
#[tracing::instrument(skip(work_dir))]
pub fn clone_or_fetch(
url: &str,
work_dir: &Path,
project_name: &str,
branch: Option<&str>,
) -> Result<(PathBuf, String)> {
let repo_path = work_dir.join(project_name);
let repo = if repo_path.exists() {
@ -19,10 +27,21 @@ pub fn clone_or_fetch(url: &str, work_dir: &Path, project_name: &str) -> Result<
Repository::clone(url, &repo_path)?
};
// Get HEAD commit hash
let head = repo.head()?;
let commit = head.peel_to_commit()?;
let hash = commit.id().to_string();
// Resolve commit: use specific branch ref or fall back to HEAD
let hash = if let Some(branch_name) = branch {
let refname = format!("refs/remotes/origin/{branch_name}");
let reference = repo.find_reference(&refname).map_err(|e| {
fc_common::error::CiError::NotFound(format!(
"Branch '{branch_name}' not found ({refname}): {e}"
))
})?;
let commit = reference.peel_to_commit()?;
commit.id().to_string()
} else {
let head = repo.head()?;
let commit = head.peel_to_commit()?;
commit.id().to_string()
};
Ok((repo_path, hash))
}