diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
commit | 10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch) | |
tree | bdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/gix/src/init.rs | |
parent | Releasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff) | |
download | rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.zip |
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/gix/src/init.rs')
-rw-r--r-- | vendor/gix/src/init.rs | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/vendor/gix/src/init.rs b/vendor/gix/src/init.rs new file mode 100644 index 000000000..d04de0806 --- /dev/null +++ b/vendor/gix/src/init.rs @@ -0,0 +1,101 @@ +#![allow(clippy::result_large_err)] +use std::{borrow::Cow, convert::TryInto, path::Path}; + +use gix_ref::{ + store::WriteReflog, + transaction::{PreviousValue, RefEdit}, + FullName, Target, +}; + +use crate::{bstr::BString, config::tree::Init, ThreadSafeRepository}; + +/// The name of the branch to use if non is configured via git configuration. +/// +/// # Deviation +/// +/// We use `main` instead of `master`. +pub const DEFAULT_BRANCH_NAME: &str = "main"; + +/// The error returned by [`crate::init()`]. +#[derive(Debug, thiserror::Error)] +#[allow(missing_docs)] +pub enum Error { + #[error("Could not obtain the current directory")] + CurrentDir(#[from] std::io::Error), + #[error(transparent)] + Init(#[from] crate::create::Error), + #[error(transparent)] + Open(#[from] crate::open::Error), + #[error("Invalid default branch name: {name:?}")] + InvalidBranchName { + name: BString, + source: gix_validate::refname::Error, + }, + #[error("Could not edit HEAD reference with new default name")] + EditHeadForDefaultBranch(#[from] crate::reference::edit::Error), +} + +impl ThreadSafeRepository { + /// Create a repository with work-tree within `directory`, creating intermediate directories as needed. + /// + /// Fails without action if there is already a `.git` repository inside of `directory`, but + /// won't mind if the `directory` otherwise is non-empty. + pub fn init( + directory: impl AsRef<Path>, + kind: crate::create::Kind, + options: crate::create::Options, + ) -> Result<Self, Error> { + 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) + } + + /// Similar to [`init`][Self::init()], but allows to determine how exactly to open the newly created repository. + /// + /// # Deviation + /// + /// Instead of naming the default branch `master`, we name it `main` unless configured explicitly using the `init.defaultBranch` + /// configuration key. + 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, Error> { + let path = crate::create::into(directory.as_ref(), kind, create_options)?; + 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 = std::env::current_dir()?.into(); + let repo = ThreadSafeRepository::open_from_paths(git_dir, worktree_dir, open_options)?; + + let branch_name = repo + .config + .resolved + .string("init", None, Init::DEFAULT_BRANCH.name) + .unwrap_or_else(|| Cow::Borrowed(DEFAULT_BRANCH_NAME.into())); + if branch_name.as_ref() != DEFAULT_BRANCH_NAME { + let sym_ref: FullName = + format!("refs/heads/{branch_name}") + .try_into() + .map_err(|err| Error::InvalidBranchName { + name: branch_name.into_owned(), + source: err, + })?; + 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 { + change: gix_ref::transaction::Change::Update { + log: Default::default(), + expected: PreviousValue::Any, + new: Target::Symbolic(sym_ref), + }, + name: "HEAD".try_into().expect("valid"), + deref: false, + })?; + repo.refs.write_reflog = prev_write_reflog; + } + + Ok(repo) + } +} |