use std::path::Path;
use gix_ref::{
Category, FullName,
store::WriteReflog,
transaction::{PreviousValue, RefEdit},
};
use crate::error::{ResultExt, message, validation};
use crate::{Result, ThreadSafeRepository, bstr::ByteSlice, config::tree::Init};
pub const DEFAULT_BRANCH_NAME: &str = "main";
impl ThreadSafeRepository {
pub fn init(
directory: impl AsRef<Path>,
kind: crate::create::Kind,
options: crate::create::Options,
) -> Result<Self> {
use gix_sec::trust::DefaultForLevel;
let open_options = crate::open::Options::default_for_level(gix_sec::Trust::Full);
Self::init_opts(directory, kind, options, open_options)
}
pub fn init_opts(
directory: impl AsRef<Path>,
kind: crate::create::Kind,
create_options: crate::create::Options,
mut open_options: crate::open::Options,
) -> Result<Self> {
let (path, capabilities) = crate::create::into_with_capabilities(directory.as_ref(), kind, create_options)?;
if !capabilities.symlink {
open_options.api_config_overrides.push("core.symlinks=false".into());
}
let (git_dir, worktree_dir) = path.into_repository_and_work_tree_directories();
open_options.git_dir_trust = Some(gix_sec::Trust::Full);
open_options.current_dir = gix_fs::current_dir(false)
.or_raise(|| message("Could not obtain the current directory"))?
.into();
let repo = ThreadSafeRepository::open_from_paths(git_dir, worktree_dir, open_options, None)?;
let branch_name = repo
.config
.resolved
.string(Init::DEFAULT_BRANCH)
.unwrap_or_else(|| DEFAULT_BRANCH_NAME.into());
if branch_name.as_bstr() != DEFAULT_BRANCH_NAME {
let configured_branch_name = branch_name;
let sym_ref: FullName = Category::LocalBranch
.to_full_name(configured_branch_name.as_bstr())
.or_raise(|| validation("Invalid default branch name").with_input(configured_branch_name.clone()))?;
gix_validate::reference::branch_name(sym_ref.as_bstr())
.or_raise(|| validation("Invalid default branch name").with_input(configured_branch_name))?;
let mut repo = repo.to_thread_local();
let prev_write_reflog = repo.refs.write_reflog;
repo.refs.write_reflog = WriteReflog::Disable;
repo.edit_reference(RefEdit::update(
"HEAD".try_into().expect("valid"),
sym_ref,
PreviousValue::Any,
"",
))
.or_raise(|| message("Could not edit HEAD reference with new default name"))?;
repo.refs.write_reflog = prev_write_reflog;
}
Ok(repo)
}
}