//! This crate provides the [`Repository`] abstraction which serves as a hub into all the functionality of git.//!//! It's powerful and won't sacrifice performance while still increasing convenience compared to using the sub-crates//! individually. Sometimes it may hide complexity under the assumption that the performance difference doesn't matter//! for all but the fewest tools out there, which would be using the underlying crates directly or file an issue.//!//! ## Example//!//! This is merely an introduction, for more see the respective [`Repository`] methods.//! ```//! # fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {//! # mod doctest { include!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/doctest.rs")); }//! # let repo_dir = doctest::basic_repo_dir()?;//! # let repo = doctest::open_repo(repo_dir)?;//! let head = repo.head_commit()?;//!//! assert_eq!(repo.head_name()?.expect("born").shorten(), "main");//! assert_eq!(head.decode()?.message, "c2\n");//! assert_eq!(repo.head_tree_id()?, head.tree_id()?);//! # Ok(()) }//! ```//!//! ### The Trust Model//!//! It is very simple - based on the ownership of the repository compared to the user of the current process [Trust](sec::Trust)//! is assigned. This can be [overridden](open::Options::with()) as well. Further, git configuration files track their trust level//! per section based on and sensitive values like paths to executables or certain values will be skipped if they are from a source//! that isn't [fully](sec::Trust::Full) trusted.//!//! That way, data can safely be obtained without risking to execute untrusted executables.//!//! Note that it's possible to let `gix` act like `git` or `git2` by setting the [open::Options::bail_if_untrusted()] option.//!//! ### The prelude and extensions//!//! With `use git_repository::prelude::*` you should be ready to go as it pulls in various extension traits to make functionality//! available on objects that may use it.//!//! The method signatures are still complex and may require various arguments for configuration and cache control.//!//! Most extensions to existing objects provide an `obj_with_extension.attach(&repo).an_easier_version_of_a_method()` for simpler//! call signatures.//!//! ### `ThreadSafe` Mode//!//! By default, the [`Repository`] isn't `Sync` and thus can't be used in certain contexts which require the `Sync` trait.//!//! To help with this, convert it with [`Repository::into_sync()`] into a [`ThreadSafeRepository`].//!//! ### Object-Access Performance//!//! Accessing objects quickly is the bread-and-butter of working with git, right after accessing references. Hence it's vital//! to understand which cache levels exist and how to leverage them.//!//! When accessing an object, the first cache that's queried is a memory-capped LRU object cache, mapping their id to data and kind.//! It has to be specifically enabled on a [`Repository`].//! On miss, the object is looked up and if a pack is hit, there is a small fixed-size cache for delta-base objects.//!//! In scenarios where the same objects are accessed multiple times, the object cache can be useful and is to be configured specifically//! using the [`Repository::object_cache_size()`] method.//!//! Use the `cache-efficiency-debug` cargo feature to learn how efficient the cache actually is - it's easy to end up with lowered//! performance if the cache is not hit in 50% of the time.//!//! ### Terminology//!//! #### `WorkingTree` and `WorkTree`//!//! When reading the documentation of the canonical gix-worktree program one gets the impression work tree and working tree are used//! interchangeably. We use the term _work tree_ only and try to do so consistently as its shorter and assumed to be the same.//!//! ### Plumbing Crates//!//! To make using _sub-crates_ and their types easier, these are re-exported into the root of this crate. Here we list how to access nested plumbing//! crates which are otherwise harder to discover://!//! **`git_repository::`**//! * [`odb`]//! * [`pack`][odb::pack]//! * [`protocol`]//! * [`transport`][protocol::transport]//! * [`packetline`][protocol::transport::packetline]//!//! ### `libgit2` API to `gix`//!//! This doc-aliases are used to help finding methods under a possibly changed name. Just search in the docs.//! Entering `git2` into the search field will also surface all methods with such annotations.//!//! What follows is a list of methods you might be missing, along with workarounds if available.//! * [`git2::Repository::open_bare()`](https://docs.rs/git2/*/git2/struct.Repository.html#method.open_bare) ➡ ❌ - use [`open()`] and discard if it is not bare.//! * [`git2::build::CheckoutBuilder::disable_filters()`](https://docs.rs/git2/*/git2/build/struct.CheckoutBuilder.html#method.disable_filters) ➡ ❌ *(filters are always applied during checkouts)*//! * [`git2::Repository::submodule_status()`](https://docs.rs/git2/*/git2/struct.Repository.html#method.submodule_status) ➡ [`Submodule::state()`] - status provides more information and conveniences though, and an actual worktree status isn't performed.//!//! #### Integrity checks//!//! `git2` by default performs integrity checks via [`strict_hash_verification()`](https://docs.rs/git2/latest/git2/opts/fn.strict_hash_verification.html) and//! [`strict_object_creation`](https://docs.rs/git2/latest/git2/opts/fn.strict_object_creation.html) which `gitoxide` *currently* **does not have**.//!//! ### Feature Flags#![cfg_attr( all(doc, feature = "document-features"), doc = ::document_features::document_features!())]#![cfg_attr(all(doc, feature = "document-features"), feature(doc_cfg))]#![deny(missing_docs, unsafe_code)]#![allow(clippy::result_large_err)] // Re-exports to make this a potential one-stop shop crate avoiding people from having to reference various crates themselves.// This also means that their major version changes affect our major version, but that's alright as we directly expose their// APIs/instances anyway.pub use gix_actor as actor;#[cfg(feature = "attributes")]pub use gix_attributes as attrs;#[cfg(feature = "blame")]pub use gix_blame as blame;#[cfg(feature = "command")]pub use gix_command as command;pub use gix_commitgraph as commitgraph;#[cfg(feature = "credentials")]pub use gix_credentials as credentials;pub use gix_date as date;#[cfg(feature = "dirwalk")]pub use gix_dir as dir;pub use gix_error as error;pub use gix_features as features;use gix_features::threading::OwnShared;pub use gix_features::{ parallel, progress::{Count, DynNestedProgress, NestedProgress, Progress}, threading,};pub use gix_fs as fs;pub use gix_glob as glob;pub use gix_hash as hash;pub use gix_hashtable as hashtable;#[cfg(feature = "excludes")]pub use gix_ignore as ignore;#[doc(inline)]#[cfg(feature = "index")]pub use gix_index as index;pub use gix_lock as lock;#[cfg(feature = "credentials")]pub use gix_negotiate as negotiate;pub use gix_object as objs;pub use gix_object::bstr;pub use gix_odb as odb;#[cfg(feature = "credentials")]pub use gix_prompt as prompt;pub use gix_protocol as protocol;pub use gix_quote as quote;pub use gix_ref as refs;pub use gix_refspec as refspec;pub use gix_revwalk as revwalk;pub use gix_sec as sec;pub use gix_tempfile as tempfile;pub use gix_trace as trace;pub use gix_traverse as traverse;pub use gix_url as url;#[doc(inline)]pub use gix_url::Url;pub use gix_utils as utils;pub use gix_validate as validate;pub use gix_zlib as zlib;pub use hash::{ObjectId, oid}; pub use gix_error::{Error, Exn}; pub mod interrupt; mod ext;///pub mod prelude; #[cfg(feature = "excludes")]mod attribute_stack; ///pub mod path; /// The standard type for a store to handle git references.pub type RefStore = gix_ref::file::Store;/// A handle for finding objects in an object database, abstracting away caches for thread-local use.pub type OdbHandle = gix_odb::memory::Proxy<gix_odb::Handle>;/// A handle for finding objects in an object database, abstracting away caches for moving across threads.pub type OdbHandleArc = gix_odb::memory::Proxy<gix_odb::HandleArc>; /// A way to access git configurationpub(crate) type Config = OwnShared<gix_config::File>; mod types;#[cfg(any(feature = "excludes", feature = "attributes"))]pub use types::AttributeStack;pub use types::{ Blob, Commit, Head, Id, Object, ObjectDetached, Reference, Remote, Repository, Tag, ThreadSafeRepository, Tree, Worktree,};#[cfg(feature = "attributes")]pub use types::{Pathspec, PathspecDetached, Submodule}; ///pub mod clone;pub mod commit;///#[cfg(feature = "dirwalk")]pub mod dirwalk;pub mod head;pub mod id;pub mod object;#[cfg(feature = "attributes")]pub mod pathspec;pub mod reference;pub mod repository;#[cfg(feature = "attributes")]pub mod submodule;pub mod tag;#[cfg(any(feature = "dirwalk", feature = "status"))]pub(crate) mod util; ///pub mod progress;///pub mod push; ///pub mod diff; ///#[cfg(feature = "merge")]pub mod merge; /// Try to open a git repository in `directory` and search upwards through its parents until one is found,/// using default trust options which matters in case the found repository isn't owned by the current user.////// For details, see [`ThreadSafeRepository::discover()`].////// # Note////// **The discovered repository might not be suitable for any operation that requires authentication with remotes**/// as it doesn't see the relevant git configuration.////// To achieve that, one has to [enable `git_binary` configuration](https://github.com/GitoxideLabs/gitoxide/blob/9723e1addf52cc336d59322de039ea0537cdca36/src/plumbing/main.rs#L86)/// in the open-options and use [`ThreadSafeRepository::discover_opts()`] instead. Alternatively, it might be well-known/// that the tool is going to run in a neatly configured environment without relying on bundled configuration.////// # Examples////// ```/// # fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {/// # mod doctest { include!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/doctest.rs")); }/// # let repo_dir = doctest::basic_repo_dir()?;/// let repo = doctest::discover_repo(repo_dir.join("some/very/deeply/nested/subdir"))?;////// assert_eq!(repo.kind(), gix::repository::Kind::Common);/// assert_eq!(repo.head_name()?.expect("born").shorten(), "main");/// assert!(repo.workdir_path("this").expect("non-bare").is_file());/// # Ok(()) }/// ```#[expect( clippy::result_large_err, reason = "will be removed once `gix-error` is used consistently")]pub fn discover(directory: impl AsRef<std::path::Path>) -> Result<Repository, discover::Error> { ThreadSafeRepository::discover(directory).map(Into::into)} /// Try to open a git repository in `directory` and search upwards through its parents until one is found,/// using `open_options` regardless of the trust level of the discovered repository./// The detected trust level is retained, so repositories with reduced trust still restrict their behavior accordingly.#[expect( clippy::result_large_err, reason = "will be removed once `gix-error` is used consistently")]pub fn discover_opts( directory: impl AsRef<std::path::Path>, options: discover::upwards::Options<'_>, open_options: open::Options,) -> Result<Repository, discover::Error> { ThreadSafeRepository::discover_opts( directory, options, sec::trust::Mapping { full: open_options.clone(), reduced: open_options, }, ) .map(Into::into)} /// Try to discover a git repository directly from the environment.////// For details, see [`ThreadSafeRepository::discover_with_environment_overrides_opts()`].#[expect( clippy::result_large_err, reason = "will be removed once `gix-error` is used consistently")]pub fn discover_with_environment_overrides( directory: impl AsRef<std::path::Path>,) -> Result<Repository, discover::Error> { ThreadSafeRepository::discover_with_environment_overrides(directory).map(Into::into)} /// Try to open a git repository directly from the environment.////// See [`ThreadSafeRepository::open_with_environment_overrides()`].#[expect( clippy::result_large_err, reason = "will be removed once `gix-error` is used consistently")]pub fn open_with_environment_overrides(directory: impl Into<std::path::PathBuf>) -> Result<Repository, open::Error> { ThreadSafeRepository::open_with_environment_overrides(directory, Default::default()).map(Into::into)} /// See [`ThreadSafeRepository::init()`], but returns a [`Repository`] instead.////// # Examples////// ```/// # fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {/// # mod doctest { include!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/doctest.rs")); }/// # let dir = doctest::tempdir()?;/// let repo = gix::init(dir.path())?;////// assert!(repo.git_dir().is_dir());/// assert!(repo.head_name()?.is_some());/// assert!(repo.head()?.is_unborn());/// # Ok(()) }/// ```#[expect( clippy::result_large_err, reason = "will be removed once `gix-error` is used consistently")]pub fn init(directory: impl AsRef<std::path::Path>) -> Result<Repository, init::Error> { ThreadSafeRepository::init(directory, create::Kind::WithWorktree, create::Options::default()).map(Into::into)} /// See [`ThreadSafeRepository::init()`], but returns a [`Repository`] instead.#[expect( clippy::result_large_err, reason = "will be removed once `gix-error` is used consistently")]pub fn init_bare(directory: impl AsRef<std::path::Path>) -> Result<Repository, init::Error> { ThreadSafeRepository::init(directory, create::Kind::Bare, create::Options::default()).map(Into::into)} /// Create a platform for configuring a bare clone from `url` to the local `path`, using default options for opening it (but/// amended with using configuration from the git installation to ensure all authentication options are honored).////// See [`clone::PrepareFetch::new()`] for a function to take full control over all options.#[expect( clippy::result_large_err, reason = "will be removed once `gix-error` is used consistently")]pub fn prepare_clone_bare<Url, E>( url: Url, path: impl AsRef<std::path::Path>,) -> Result<clone::PrepareFetch, clone::Error>where Url: std::convert::TryInto<gix_url::Url, Error = E>, gix_url::parse::Error: From<E>,{ clone::PrepareFetch::new( url, path, create::Kind::Bare, create::Options::default(), open_opts_with_git_binary_config(), )} /// Create a platform for configuring a clone with main working tree from `url` to the local `path`, using default options for opening it/// (but amended with using configuration from the git installation to ensure all authentication options are honored).////// See [`clone::PrepareFetch::new()`] for a function to take full control over all options.#[expect( clippy::result_large_err, reason = "will be removed once `gix-error` is used consistently")]pub fn prepare_clone<Url, E>(url: Url, path: impl AsRef<std::path::Path>) -> Result<clone::PrepareFetch, clone::Error>where Url: std::convert::TryInto<gix_url::Url, Error = E>, gix_url::parse::Error: From<E>,{ clone::PrepareFetch::new( url, path, create::Kind::WithWorktree, create::Options::default(), open_opts_with_git_binary_config(), )} fn open_opts_with_git_binary_config() -> open::Options { use gix_sec::trust::DefaultForLevel; let mut opts = open::Options::default_for_level(gix_sec::Trust::Full); opts.permissions.config.git_binary = true; opts} /// See [`ThreadSafeRepository::open()`], but returns a [`Repository`] instead.////// # Examples////// ```/// # fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {/// # mod doctest { include!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/doctest.rs")); }/// # let repo_dir = doctest::basic_repo_dir()?;/// let repo = doctest::open_repo(repo_dir)?;////// assert_eq!(repo.head_name()?.expect("born").shorten(), "main");/// assert_eq!(repo.head_commit()?.decode()?.message, "c2\n");/// # Ok(()) }/// ```#[expect( clippy::result_large_err, reason = "will be removed once `gix-error` is used consistently")]#[doc(alias = "git2")]pub fn open(directory: impl Into<std::path::PathBuf>) -> Result<Repository, open::Error> { ThreadSafeRepository::open(directory).map(Into::into)} /// See [`ThreadSafeRepository::open_opts()`], but returns a [`Repository`] instead.#[expect( clippy::result_large_err, reason = "will be removed once `gix-error` is used consistently")]#[doc(alias = "open_ext", alias = "git2")]pub fn open_opts(directory: impl Into<std::path::PathBuf>, options: open::Options) -> Result<Repository, open::Error> { ThreadSafeRepository::open_opts(directory, options).map(Into::into)} /// Load configuration available without an existing repository, using the configuration-related portions of `options`.////// `git_dir` supplies context for `includeIf.gitdir` conditions and does not have to exist. Without it, these/// conditions aren't matched. Repository-local and branch-dependent configuration isn't available at this stage.pub fn config(git_dir: Option<&std::path::Path>, options: &open::Options) -> Result<config::File, config::Error> { let environment = options.permissions.env; let git_install_dir = path::install_dir().ok(); let home = gix_path::env::home_dir().and_then(|home| environment.home.check_opt(home)); config::cache::load( None, &mut Vec::new(), git_dir, None, git_install_dir.as_deref(), home.as_deref(), options.git_installation_config_path.as_deref(), options.system_config_path.as_deref(), environment, options.permissions.config, options.lossy_config, options.lenient_config, &options.api_config_overrides, &options.cli_config_overrides, options.use_repository_local_environment, )} /// Return the path at which a configuration file is expected without a repository, selected by its source.////// Supported sources are [`GitInstallation`](config::Source::GitInstallation), [`System`](config::Source::System),/// [`Git`](config::Source::Git) (the XDG Git configuration), and [`User`](config::Source::User)./// Path selection honors the configuration permissions, environment permissions and explicit paths in `options`,/// just like [`config()`]. Disabled sources and sources without an available path return an error./// Relative paths are joined to the current directory when called.////// With a repository, use [`Repository::config_path()`] to also resolve local and worktree configuration paths.////// Use this to inspect, prepare or load the file before calling [`config_mut()`]. The file and its parent directories/// do not have to exist. No configuration transaction is opened, no lock is acquired, and no directories are created./// Discovering the Git installation path, or the system path on Windows, may invoke Git.pub fn config_path( source: config::Source, options: &open::Options,) -> Result<std::path::PathBuf, config::file_mut::Error> { use config::file_mut::Error; if !matches!( source, config::Source::GitInstallation | config::Source::System | config::Source::Git | config::Source::User ) { return Err(Error::UnsupportedSource(source)); } let path = config::cache::source_path( source, options.git_installation_config_path.as_deref(), options.system_config_path.as_deref(), options.permissions.config, &mut config::Cache::make_source_env(options.permissions.env), ) .ok_or(Error::SourceUnavailable(source))?; Ok(if path.is_absolute() { path } else { std::env::current_dir().map_err(Error::CurrentDir)?.join(path) })} /// Lock and open one configuration file available without a repository, selected by its source.///Lines 1–500 of 591. Load more
//! This crate provides the [`Repository`] abstraction which serves as a hub into all the functionality of git. //! //! It's powerful and won't sacrifice performance while still increasing convenience compared to using the sub-crates //! individually. Sometimes it may hide complexity under the assumption that the performance difference doesn't matter //! for all but the fewest tools out there, which would be using the underlying crates directly or file an issue. //! //! ## Example //! //! This is merely an introduction, for more see the respective [`Repository`] methods. //! ``` //! # fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { //! # mod doctest { include!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/doctest.rs")); } //! # let repo_dir = doctest::basic_repo_dir()?; //! # let repo = doctest::open_repo(repo_dir)?; //! let head = repo.head_commit()?; //! //! assert_eq!(repo.head_name()?.expect("born").shorten(), "main"); //! assert_eq!(head.decode()?.message, "c2\n"); //! assert_eq!(repo.head_tree_id()?, head.tree_id()?); //! # Ok(()) } //! ``` //! //! ### The Trust Model //! //! It is very simple - based on the ownership of the repository compared to the user of the current process [Trust](sec::Trust) //! is assigned. This can be [overridden](open::Options::with()) as well. Further, git configuration files track their trust level //! per section based on and sensitive values like paths to executables or certain values will be skipped if they are from a source //! that isn't [fully](sec::Trust::Full) trusted. //! //! That way, data can safely be obtained without risking to execute untrusted executables. //! //! Note that it's possible to let `gix` act like `git` or `git2` by setting the [open::Options::bail_if_untrusted()] option. //! //! ### The prelude and extensions //! //! With `use git_repository::prelude::*` you should be ready to go as it pulls in various extension traits to make functionality //! available on objects that may use it. //! //! The method signatures are still complex and may require various arguments for configuration and cache control. //! //! Most extensions to existing objects provide an `obj_with_extension.attach(&repo).an_easier_version_of_a_method()` for simpler //! call signatures. //! //! ### `ThreadSafe` Mode //! //! By default, the [`Repository`] isn't `Sync` and thus can't be used in certain contexts which require the `Sync` trait. //! //! To help with this, convert it with [`Repository::into_sync()`] into a [`ThreadSafeRepository`]. //! //! ### Object-Access Performance //! //! Accessing objects quickly is the bread-and-butter of working with git, right after accessing references. Hence it's vital //! to understand which cache levels exist and how to leverage them. //! //! When accessing an object, the first cache that's queried is a memory-capped LRU object cache, mapping their id to data and kind. //! It has to be specifically enabled on a [`Repository`]. //! On miss, the object is looked up and if a pack is hit, there is a small fixed-size cache for delta-base objects. //! //! In scenarios where the same objects are accessed multiple times, the object cache can be useful and is to be configured specifically //! using the [`Repository::object_cache_size()`] method. //! //! Use the `cache-efficiency-debug` cargo feature to learn how efficient the cache actually is - it's easy to end up with lowered //! performance if the cache is not hit in 50% of the time. //! //! ### Terminology //! //! #### `WorkingTree` and `WorkTree` //! //! When reading the documentation of the canonical gix-worktree program one gets the impression work tree and working tree are used //! interchangeably. We use the term _work tree_ only and try to do so consistently as its shorter and assumed to be the same. //! //! ### Plumbing Crates //! //! To make using _sub-crates_ and their types easier, these are re-exported into the root of this crate. Here we list how to access nested plumbing //! crates which are otherwise harder to discover: //! //! **`git_repository::`** //! * [`odb`] //! * [`pack`][odb::pack] //! * [`protocol`] //! * [`transport`][protocol::transport] //! * [`packetline`][protocol::transport::packetline] //! //! ### `libgit2` API to `gix` //! //! This doc-aliases are used to help finding methods under a possibly changed name. Just search in the docs. //! Entering `git2` into the search field will also surface all methods with such annotations. //! //! What follows is a list of methods you might be missing, along with workarounds if available. //! * [`git2::Repository::open_bare()`](https://docs.rs/git2/*/git2/struct.Repository.html#method.open_bare) ➡ ❌ - use [`open()`] and discard if it is not bare. //! * [`git2::build::CheckoutBuilder::disable_filters()`](https://docs.rs/git2/*/git2/build/struct.CheckoutBuilder.html#method.disable_filters) ➡ ❌ *(filters are always applied during checkouts)* //! * [`git2::Repository::submodule_status()`](https://docs.rs/git2/*/git2/struct.Repository.html#method.submodule_status) ➡ [`Submodule::state()`] - status provides more information and conveniences though, and an actual worktree status isn't performed. //! //! #### Integrity checks //! //! `git2` by default performs integrity checks via [`strict_hash_verification()`](https://docs.rs/git2/latest/git2/opts/fn.strict_hash_verification.html) and //! [`strict_object_creation`](https://docs.rs/git2/latest/git2/opts/fn.strict_object_creation.html) which `gitoxide` *currently* **does not have**. //! //! ### Feature Flags #![cfg_attr( all(doc, feature = "document-features"), doc = ::document_features::document_features!() )] #![cfg_attr(all(doc, feature = "document-features"), feature(doc_cfg))] #![deny(missing_docs, unsafe_code)] #![allow(clippy::result_large_err)] // Re-exports to make this a potential one-stop shop crate avoiding people from having to reference various crates themselves. // This also means that their major version changes affect our major version, but that's alright as we directly expose their // APIs/instances anyway. pub use gix_actor as actor; #[cfg(feature = "attributes")] pub use gix_attributes as attrs; #[cfg(feature = "blame")] pub use gix_blame as blame; #[cfg(feature = "command")] pub use gix_command as command; pub use gix_commitgraph as commitgraph; #[cfg(feature = "credentials")] pub use gix_credentials as credentials; pub use gix_date as date; #[cfg(feature = "dirwalk")] pub use gix_dir as dir; pub use gix_error as error; pub use gix_features as features; use gix_features::threading::OwnShared; pub use gix_features::{ parallel, progress::{Count, DynNestedProgress, NestedProgress, Progress}, threading, }; pub use gix_fs as fs; pub use gix_glob as glob; pub use gix_hash as hash; pub use gix_hashtable as hashtable; #[cfg(feature = "excludes")] pub use gix_ignore as ignore; #[doc(inline)] #[cfg(feature = "index")] pub use gix_index as index; pub use gix_lock as lock; #[cfg(feature = "credentials")] pub use gix_negotiate as negotiate; pub use gix_object as objs; pub use gix_object::bstr; pub use gix_odb as odb; #[cfg(feature = "credentials")] pub use gix_prompt as prompt; pub use gix_protocol as protocol; pub use gix_quote as quote; pub use gix_ref as refs; pub use gix_refspec as refspec; pub use gix_revwalk as revwalk; pub use gix_sec as sec; pub use gix_tempfile as tempfile; pub use gix_trace as trace; pub use gix_traverse as traverse; pub use gix_url as url; #[doc(inline)] pub use gix_url::Url; pub use gix_utils as utils; pub use gix_validate as validate; pub use gix_zlib as zlib; pub use hash::{ObjectId, oid}; pub use gix_error::{Error, Exn}; pub mod interrupt; mod ext; /// pub mod prelude; #[cfg(feature = "excludes")] mod attribute_stack; /// pub mod path; /// The standard type for a store to handle git references. pub type RefStore = gix_ref::file::Store; /// A handle for finding objects in an object database, abstracting away caches for thread-local use. pub type OdbHandle = gix_odb::memory::Proxy<gix_odb::Handle>; /// A handle for finding objects in an object database, abstracting away caches for moving across threads. pub type OdbHandleArc = gix_odb::memory::Proxy<gix_odb::HandleArc>; /// A way to access git configuration pub(crate) type Config = OwnShared<gix_config::File>; mod types; #[cfg(any(feature = "excludes", feature = "attributes"))] pub use types::AttributeStack; pub use types::{ Blob, Commit, Head, Id, Object, ObjectDetached, Reference, Remote, Repository, Tag, ThreadSafeRepository, Tree, Worktree, }; #[cfg(feature = "attributes")] pub use types::{Pathspec, PathspecDetached, Submodule}; /// pub mod clone; pub mod commit; /// #[cfg(feature = "dirwalk")] pub mod dirwalk; pub mod head; pub mod id; pub mod object; #[cfg(feature = "attributes")] pub mod pathspec; pub mod reference; pub mod repository; #[cfg(feature = "attributes")] pub mod submodule; pub mod tag; #[cfg(any(feature = "dirwalk", feature = "status"))] pub(crate) mod util; /// pub mod progress; /// pub mod push; /// pub mod diff; /// #[cfg(feature = "merge")] pub mod merge; /// Try to open a git repository in `directory` and search upwards through its parents until one is found, /// using default trust options which matters in case the found repository isn't owned by the current user. /// /// For details, see [`ThreadSafeRepository::discover()`]. /// /// # Note /// /// **The discovered repository might not be suitable for any operation that requires authentication with remotes** /// as it doesn't see the relevant git configuration. /// /// To achieve that, one has to [enable `git_binary` configuration](https://github.com/GitoxideLabs/gitoxide/blob/9723e1addf52cc336d59322de039ea0537cdca36/src/plumbing/main.rs#L86) /// in the open-options and use [`ThreadSafeRepository::discover_opts()`] instead. Alternatively, it might be well-known /// that the tool is going to run in a neatly configured environment without relying on bundled configuration. /// /// # Examples /// /// ``` /// # fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { /// # mod doctest { include!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/doctest.rs")); } /// # let repo_dir = doctest::basic_repo_dir()?; /// let repo = doctest::discover_repo(repo_dir.join("some/very/deeply/nested/subdir"))?; /// /// assert_eq!(repo.kind(), gix::repository::Kind::Common); /// assert_eq!(repo.head_name()?.expect("born").shorten(), "main"); /// assert!(repo.workdir_path("this").expect("non-bare").is_file()); /// # Ok(()) } /// ``` #[expect( clippy::result_large_err, reason = "will be removed once `gix-error` is used consistently" )] pub fn discover(directory: impl AsRef<std::path::Path>) -> Result<Repository, discover::Error> { ThreadSafeRepository::discover(directory).map(Into::into) } /// Try to open a git repository in `directory` and search upwards through its parents until one is found, /// using `open_options` regardless of the trust level of the discovered repository. /// The detected trust level is retained, so repositories with reduced trust still restrict their behavior accordingly. #[expect( clippy::result_large_err, reason = "will be removed once `gix-error` is used consistently" )] pub fn discover_opts( directory: impl AsRef<std::path::Path>, options: discover::upwards::Options<'_>, open_options: open::Options, ) -> Result<Repository, discover::Error> { ThreadSafeRepository::discover_opts( directory, options, sec::trust::Mapping { full: open_options.clone(), reduced: open_options, }, ) .map(Into::into) } /// Try to discover a git repository directly from the environment. /// /// For details, see [`ThreadSafeRepository::discover_with_environment_overrides_opts()`]. #[expect( clippy::result_large_err, reason = "will be removed once `gix-error` is used consistently" )] pub fn discover_with_environment_overrides( directory: impl AsRef<std::path::Path>, ) -> Result<Repository, discover::Error> { ThreadSafeRepository::discover_with_environment_overrides(directory).map(Into::into) } /// Try to open a git repository directly from the environment. /// /// See [`ThreadSafeRepository::open_with_environment_overrides()`]. #[expect( clippy::result_large_err, reason = "will be removed once `gix-error` is used consistently" )] pub fn open_with_environment_overrides(directory: impl Into<std::path::PathBuf>) -> Result<Repository, open::Error> { ThreadSafeRepository::open_with_environment_overrides(directory, Default::default()).map(Into::into) } /// See [`ThreadSafeRepository::init()`], but returns a [`Repository`] instead. /// /// # Examples /// /// ``` /// # fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { /// # mod doctest { include!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/doctest.rs")); } /// # let dir = doctest::tempdir()?; /// let repo = gix::init(dir.path())?; /// /// assert!(repo.git_dir().is_dir()); /// assert!(repo.head_name()?.is_some()); /// assert!(repo.head()?.is_unborn()); /// # Ok(()) } /// ``` #[expect( clippy::result_large_err, reason = "will be removed once `gix-error` is used consistently" )] pub fn init(directory: impl AsRef<std::path::Path>) -> Result<Repository, init::Error> { ThreadSafeRepository::init(directory, create::Kind::WithWorktree, create::Options::default()).map(Into::into) } /// See [`ThreadSafeRepository::init()`], but returns a [`Repository`] instead. #[expect( clippy::result_large_err, reason = "will be removed once `gix-error` is used consistently" )] pub fn init_bare(directory: impl AsRef<std::path::Path>) -> Result<Repository, init::Error> { ThreadSafeRepository::init(directory, create::Kind::Bare, create::Options::default()).map(Into::into) } /// Create a platform for configuring a bare clone from `url` to the local `path`, using default options for opening it (but /// amended with using configuration from the git installation to ensure all authentication options are honored). /// /// See [`clone::PrepareFetch::new()`] for a function to take full control over all options. #[expect( clippy::result_large_err, reason = "will be removed once `gix-error` is used consistently" )] pub fn prepare_clone_bare<Url, E>( url: Url, path: impl AsRef<std::path::Path>, ) -> Result<clone::PrepareFetch, clone::Error> where Url: std::convert::TryInto<gix_url::Url, Error = E>, gix_url::parse::Error: From<E>, { clone::PrepareFetch::new( url, path, create::Kind::Bare, create::Options::default(), open_opts_with_git_binary_config(), ) } /// Create a platform for configuring a clone with main working tree from `url` to the local `path`, using default options for opening it /// (but amended with using configuration from the git installation to ensure all authentication options are honored). /// /// See [`clone::PrepareFetch::new()`] for a function to take full control over all options. #[expect( clippy::result_large_err, reason = "will be removed once `gix-error` is used consistently" )] pub fn prepare_clone<Url, E>(url: Url, path: impl AsRef<std::path::Path>) -> Result<clone::PrepareFetch, clone::Error> where Url: std::convert::TryInto<gix_url::Url, Error = E>, gix_url::parse::Error: From<E>, { clone::PrepareFetch::new( url, path, create::Kind::WithWorktree, create::Options::default(), open_opts_with_git_binary_config(), ) } fn open_opts_with_git_binary_config() -> open::Options { use gix_sec::trust::DefaultForLevel; let mut opts = open::Options::default_for_level(gix_sec::Trust::Full); opts.permissions.config.git_binary = true; opts } /// See [`ThreadSafeRepository::open()`], but returns a [`Repository`] instead. /// /// # Examples /// /// ``` /// # fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { /// # mod doctest { include!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/doctest.rs")); } /// # let repo_dir = doctest::basic_repo_dir()?; /// let repo = doctest::open_repo(repo_dir)?; /// /// assert_eq!(repo.head_name()?.expect("born").shorten(), "main"); /// assert_eq!(repo.head_commit()?.decode()?.message, "c2\n"); /// # Ok(()) } /// ``` #[expect( clippy::result_large_err, reason = "will be removed once `gix-error` is used consistently" )] #[doc(alias = "git2")] pub fn open(directory: impl Into<std::path::PathBuf>) -> Result<Repository, open::Error> { ThreadSafeRepository::open(directory).map(Into::into) } /// See [`ThreadSafeRepository::open_opts()`], but returns a [`Repository`] instead. #[expect( clippy::result_large_err, reason = "will be removed once `gix-error` is used consistently" )] #[doc(alias = "open_ext", alias = "git2")] pub fn open_opts(directory: impl Into<std::path::PathBuf>, options: open::Options) -> Result<Repository, open::Error> { ThreadSafeRepository::open_opts(directory, options).map(Into::into) } /// Load configuration available without an existing repository, using the configuration-related portions of `options`. /// /// `git_dir` supplies context for `includeIf.gitdir` conditions and does not have to exist. Without it, these /// conditions aren't matched. Repository-local and branch-dependent configuration isn't available at this stage. pub fn config(git_dir: Option<&std::path::Path>, options: &open::Options) -> Result<config::File, config::Error> { let environment = options.permissions.env; let git_install_dir = path::install_dir().ok(); let home = gix_path::env::home_dir().and_then(|home| environment.home.check_opt(home)); config::cache::load( None, &mut Vec::new(), git_dir, None, git_install_dir.as_deref(), home.as_deref(), options.git_installation_config_path.as_deref(), options.system_config_path.as_deref(), environment, options.permissions.config, options.lossy_config, options.lenient_config, &options.api_config_overrides, &options.cli_config_overrides, options.use_repository_local_environment, ) } /// Return the path at which a configuration file is expected without a repository, selected by its source. /// /// Supported sources are [`GitInstallation`](config::Source::GitInstallation), [`System`](config::Source::System), /// [`Git`](config::Source::Git) (the XDG Git configuration), and [`User`](config::Source::User). /// Path selection honors the configuration permissions, environment permissions and explicit paths in `options`, /// just like [`config()`]. Disabled sources and sources without an available path return an error. /// Relative paths are joined to the current directory when called. /// /// With a repository, use [`Repository::config_path()`] to also resolve local and worktree configuration paths. /// /// Use this to inspect, prepare or load the file before calling [`config_mut()`]. The file and its parent directories /// do not have to exist. No configuration transaction is opened, no lock is acquired, and no directories are created. /// Discovering the Git installation path, or the system path on Windows, may invoke Git. pub fn config_path( source: config::Source, options: &open::Options, ) -> Result<std::path::PathBuf, config::file_mut::Error> { use config::file_mut::Error; if !matches!( source, config::Source::GitInstallation | config::Source::System | config::Source::Git | config::Source::User ) { return Err(Error::UnsupportedSource(source)); } let path = config::cache::source_path( source, options.git_installation_config_path.as_deref(), options.system_config_path.as_deref(), options.permissions.config, &mut config::Cache::make_source_env(options.permissions.env), ) .ok_or(Error::SourceUnavailable(source))?; Ok(if path.is_absolute() { path } else { std::env::current_dir().map_err(Error::CurrentDir)?.join(path) }) } /// Lock and open one configuration file available without a repository, selected by its source. ///