use std::{env, error::Error, fs, path::PathBuf}; use git2::{Repository, Signature}; pub fn pakker_bin_path() -> PathBuf { let manifest = env!("CARGO_MANIFEST_DIR"); PathBuf::from(manifest).join("target/debug/pakker") } pub fn init_bare_repo(path: &PathBuf) -> Result { Repository::init_bare(path) } pub fn init_repo_with_commit( path: &PathBuf, file: &str, content: &str, ) -> Result> { let repo = Repository::init(path)?; let sig = Signature::now("Test User", "test@example.com")?; let workdir = repo.workdir().ok_or("no workdir")?; let file_path = workdir.join(file); fs::write(&file_path, content)?; let mut index = repo.index()?; index.add_path(std::path::Path::new(file))?; index.write()?; let tree_oid = index.write_tree()?; let tree = repo.find_tree(tree_oid)?; // initial commit let commit_oid = repo.commit(Some("HEAD"), &sig, &sig, "initial", &tree, &[])?; // create/ensure master branch points to this commit and set HEAD repo.reference("refs/heads/master", commit_oid, true, "create master")?; repo.set_head("refs/heads/master")?; // drop tree to avoid holding a borrow of `repo` when returning it drop(tree); Ok(repo) } pub fn push_to_remote( repo: &Repository, remote_name: &str, remote_url: &str, ) -> Result<(), git2::Error> { // Try to create the remote; if it already exists, find it instead let mut remote = match repo.remote(remote_name, remote_url) { Ok(r) => r, Err(_) => repo.find_remote(remote_name)?, }; // Push current HEAD to refs/heads/master on remote remote.push(&["HEAD:refs/heads/master"], None)?; // If remote is a local filesystem path, ensure its HEAD points to master if remote_url.starts_with('/') && let Ok(bare) = Repository::open(remote_url) { // Set bare repo HEAD to refs/heads/master let _ = bare.set_head("refs/heads/master"); } Ok(()) }