use std::path::Path;
use std::{io, ops::Sub, thread::sleep, time::Duration};
use anyhow::Result;
use git2::{Repository, RepositoryInitOptions};
use log::warn;
use remove_dir_all::remove_dir_all;
pub use utils::clone_git_template_into_temp;
mod clone_tool;
mod gitconfig;
mod utils;
pub use utils::{tmp_dir, try_get_branch_from_path};
type Git2Result<T> = Result<T, git2::Error>;
pub fn init(project_dir: &Path, branch: Option<&str>, force: bool) -> Git2Result<Repository> {
Repository::discover(project_dir).map_or_else(
|_| just_init(project_dir, branch),
|repo| {
if force {
Repository::open(project_dir).or_else(|_| just_init(project_dir, branch))
} else {
Ok(repo)
}
},
)
}
fn just_init(project_dir: &Path, branch: Option<&str>) -> Git2Result<Repository> {
let mut opts = RepositoryInitOptions::new();
opts.bare(false);
if let Some(branch) = branch {
opts.initial_head(branch);
}
Repository::init_opts(project_dir, &opts)
}
pub fn remove_history(project_dir: &Path) -> io::Result<()> {
let git_dir = project_dir.join(".git");
if git_dir.exists() && git_dir.is_dir() {
let mut attempt = 0_u8;
loop {
attempt += 1;
if let Err(e) = remove_dir_all(&git_dir) {
if attempt == 5 {
return Err(e);
}
if e.to_string().contains("The process cannot access the file because it is being used by another process.") {
let wait_for = Duration::from_secs(2_u64.pow(attempt.sub(1).into()));
warn!("Git history cleanup failed with a windows process blocking error. [Retry in {wait_for:?}]");
sleep(wait_for);
} else {
return Err(e);
}
} else {
return Ok(());
}
}
} else {
Ok(())
}
}