diff options
Diffstat (limited to 'vendor/gix/src')
-rw-r--r-- | vendor/gix/src/clone/fetch/mod.rs | 4 | ||||
-rw-r--r-- | vendor/gix/src/clone/fetch/util.rs | 2 | ||||
-rw-r--r-- | vendor/gix/src/config/cache/access.rs | 10 | ||||
-rw-r--r-- | vendor/gix/src/config/tree/keys.rs | 2 | ||||
-rw-r--r-- | vendor/gix/src/config/tree/sections/core.rs | 3 | ||||
-rw-r--r-- | vendor/gix/src/filter.rs | 4 | ||||
-rw-r--r-- | vendor/gix/src/head/peel.rs | 4 | ||||
-rw-r--r-- | vendor/gix/src/lib.rs | 8 | ||||
-rw-r--r-- | vendor/gix/src/object/blob.rs | 26 | ||||
-rw-r--r-- | vendor/gix/src/object/commit.rs | 8 | ||||
-rw-r--r-- | vendor/gix/src/object/impls.rs | 56 | ||||
-rw-r--r-- | vendor/gix/src/object/mod.rs | 19 | ||||
-rw-r--r-- | vendor/gix/src/object/tag.rs | 26 | ||||
-rw-r--r-- | vendor/gix/src/object/tree/mod.rs | 26 | ||||
-rw-r--r-- | vendor/gix/src/reference/errors.rs | 23 | ||||
-rw-r--r-- | vendor/gix/src/reference/mod.rs | 2 | ||||
-rw-r--r-- | vendor/gix/src/repository/cache.rs | 2 | ||||
-rw-r--r-- | vendor/gix/src/repository/index.rs | 10 | ||||
-rw-r--r-- | vendor/gix/src/repository/location.rs | 1 | ||||
-rw-r--r-- | vendor/gix/src/repository/object.rs | 49 | ||||
-rw-r--r-- | vendor/gix/src/repository/reference.rs | 9 | ||||
-rw-r--r-- | vendor/gix/src/types.rs | 20 |
22 files changed, 269 insertions, 45 deletions
diff --git a/vendor/gix/src/clone/fetch/mod.rs b/vendor/gix/src/clone/fetch/mod.rs index c03b8f839..663822212 100644 --- a/vendor/gix/src/clone/fetch/mod.rs +++ b/vendor/gix/src/clone/fetch/mod.rs @@ -94,7 +94,7 @@ impl PrepareFetch { .expect("valid static spec"); let mut clone_fetch_tags = None; if let Some(f) = self.configure_remote.as_mut() { - remote = f(remote).map_err(|err| Error::RemoteConfiguration(err))?; + remote = f(remote).map_err(Error::RemoteConfiguration)?; } else { clone_fetch_tags = remote::fetch::Tags::All.into(); } @@ -117,7 +117,7 @@ impl PrepareFetch { let pending_pack: remote::fetch::Prepare<'_, '_, _> = { let mut connection = remote.connect(remote::Direction::Fetch).await?; if let Some(f) = self.configure_connection.as_mut() { - f(&mut connection).map_err(|err| Error::RemoteConnection(err))?; + f(&mut connection).map_err(Error::RemoteConnection)?; } connection .prepare_fetch(&mut *progress, { diff --git a/vendor/gix/src/clone/fetch/util.rs b/vendor/gix/src/clone/fetch/util.rs index ab90435d0..db9bc0a1c 100644 --- a/vendor/gix/src/clone/fetch/util.rs +++ b/vendor/gix/src/clone/fetch/util.rs @@ -189,7 +189,7 @@ fn setup_branch_config( remote_name: &BStr, ) -> Result<(), Error> { let short_name = match branch.category_and_short_name() { - Some((cat, shortened)) if cat == gix_ref::Category::LocalBranch => match shortened.to_str() { + Some((gix_ref::Category::LocalBranch, shortened)) => match shortened.to_str() { Ok(s) => s, Err(_) => return Ok(()), }, diff --git a/vendor/gix/src/config/cache/access.rs b/vendor/gix/src/config/cache/access.rs index 352bc9712..3e763c028 100644 --- a/vendor/gix/src/config/cache/access.rs +++ b/vendor/gix/src/config/cache/access.rs @@ -158,13 +158,7 @@ impl Cache { pub(crate) fn stat_options(&self) -> Result<gix_index::entry::stat::Options, config::stat_options::Error> { use crate::config::tree::gitoxide; Ok(gix_index::entry::stat::Options { - trust_ctime: boolean( - self, - "core.trustCTime", - &Core::TRUST_C_TIME, - // For now, on MacOS it's known to not be trust-worthy at least with the Rust STDlib, being 2s off - !cfg!(target_os = "macos"), - )?, + trust_ctime: boolean(self, "core.trustCTime", &Core::TRUST_C_TIME, true)?, use_nsec: boolean(self, "gitoxide.core.useNsec", &gitoxide::Core::USE_NSEC, false)?, use_stdev: boolean(self, "gitoxide.core.useStdev", &gitoxide::Core::USE_STDEV, false)?, check_stat: self @@ -309,7 +303,7 @@ impl Cache { &gitoxide::Pathspec::LITERAL, ] .iter() - .find_map(|key| (key.environment_override().expect("set") == name).then_some(key)) + .find(|key| key.environment_override().expect("set") == name) .expect("we must know all possible input variable names"); let val = self diff --git a/vendor/gix/src/config/tree/keys.rs b/vendor/gix/src/config/tree/keys.rs index 5a5257af5..15cfba2d9 100644 --- a/vendor/gix/src/config/tree/keys.rs +++ b/vendor/gix/src/config/tree/keys.rs @@ -237,7 +237,7 @@ mod lock_timeout { let value = value.map_err(|err| config::lock_timeout::Error::from(self).with_source(err))?; Ok(match value { val if val < 0 => Fail::AfterDurationWithBackoff(Duration::from_secs(u64::MAX)), - val if val == 0 => Fail::Immediately, + 0 => Fail::Immediately, val => Fail::AfterDurationWithBackoff(Duration::from_millis( val.try_into().expect("i64 to u64 always works if positive"), )), diff --git a/vendor/gix/src/config/tree/sections/core.rs b/vendor/gix/src/config/tree/sections/core.rs index ab3e2bab9..2ec5c279e 100644 --- a/vendor/gix/src/config/tree/sections/core.rs +++ b/vendor/gix/src/config/tree/sections/core.rs @@ -45,8 +45,7 @@ impl Core { /// The `core.symlinks` key. pub const SYMLINKS: keys::Boolean = keys::Boolean::new_boolean("symlinks", &config::Tree::CORE); /// The `core.trustCTime` key. - pub const TRUST_C_TIME: keys::Boolean = keys::Boolean::new_boolean("trustCTime", &config::Tree::CORE) - .with_deviation("Currently the default is false, instead of true, as it seems to be 2s off in tests"); + pub const TRUST_C_TIME: keys::Boolean = keys::Boolean::new_boolean("trustCTime", &config::Tree::CORE); /// The `core.worktree` key. pub const WORKTREE: keys::Any = keys::Any::new("worktree", &config::Tree::CORE) .with_environment_override("GIT_WORK_TREE") diff --git a/vendor/gix/src/filter.rs b/vendor/gix/src/filter.rs index 935c91108..b106840a7 100644 --- a/vendor/gix/src/filter.rs +++ b/vendor/gix/src/filter.rs @@ -150,8 +150,8 @@ impl<'repo> Pipeline<'repo> { &mut |_, attrs| { entry.matching_attributes(attrs); }, - &mut |rela_path, buf| -> Result<_, gix_odb::find::Error> { - let entry = match index.entry_by_path(rela_path) { + &mut |buf| -> Result<_, gix_odb::find::Error> { + let entry = match index.entry_by_path(gix_path::into_bstr(rela_path).as_ref()) { None => return Ok(None), Some(entry) => entry, }; diff --git a/vendor/gix/src/head/peel.rs b/vendor/gix/src/head/peel.rs index a4f7c71b0..88e23636f 100644 --- a/vendor/gix/src/head/peel.rs +++ b/vendor/gix/src/head/peel.rs @@ -47,6 +47,10 @@ impl<'repo> Head<'repo> { } // TODO: tests + // TODO: Fix this! It's not consistently peeling tags. The whole peeling business should be reconsidered to do what people usually + // want which is to peel references, if present, and then peel objects with control over which object type to end at. + // Finding a good interface for that isn't easy as ideally, it's an iterator that shows the intermediate objects so the user + // can select which tag of a chain to choose. /// Follow the symbolic reference of this head until its target object and peel it by following tag objects until there is no /// more object to follow, and return that object id. /// diff --git a/vendor/gix/src/lib.rs b/vendor/gix/src/lib.rs index 672d5c91c..8218defc8 100644 --- a/vendor/gix/src/lib.rs +++ b/vendor/gix/src/lib.rs @@ -75,6 +75,11 @@ //! * [`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( feature = "document-features", @@ -158,7 +163,8 @@ mod types; #[cfg(any(feature = "excludes", feature = "attributes"))] pub use types::AttributeStack; pub use types::{ - Commit, Head, Id, Object, ObjectDetached, Reference, Remote, Repository, Tag, ThreadSafeRepository, Tree, Worktree, + Blob, Commit, Head, Id, Object, ObjectDetached, Reference, Remote, Repository, Tag, ThreadSafeRepository, Tree, + Worktree, }; #[cfg(feature = "attributes")] pub use types::{Pathspec, PathspecDetached, Submodule}; diff --git a/vendor/gix/src/object/blob.rs b/vendor/gix/src/object/blob.rs index 00b3519ed..ef19c302a 100644 --- a/vendor/gix/src/object/blob.rs +++ b/vendor/gix/src/object/blob.rs @@ -1,3 +1,5 @@ +use crate::{Blob, ObjectDetached}; + /// #[cfg(feature = "blob-diff")] pub mod diff { @@ -147,3 +149,27 @@ pub mod diff { } } } + +/// Remove Lifetime +impl Blob<'_> { + /// Create an owned instance of this object, copying our data in the process. + pub fn detached(&self) -> ObjectDetached { + ObjectDetached { + id: self.id, + kind: gix_object::Kind::Blob, + data: self.data.clone(), + } + } + + /// Sever the connection to the `Repository` and turn this instance into a standalone object. + pub fn detach(self) -> ObjectDetached { + self.into() + } + + /// Retrieve this instance's data, leaving its own data empty. + /// + /// This method works around the immovability of members of this type. + pub fn take_data(&mut self) -> Vec<u8> { + std::mem::take(&mut self.data) + } +} diff --git a/vendor/gix/src/object/commit.rs b/vendor/gix/src/object/commit.rs index 1fb9eff67..bb2e3a99e 100644 --- a/vendor/gix/src/object/commit.rs +++ b/vendor/gix/src/object/commit.rs @@ -20,6 +20,7 @@ mod error { pub use error::Error; +/// Remove Lifetime impl<'repo> Commit<'repo> { /// Create an owned instance of this object, copying our data in the process. pub fn detached(&self) -> ObjectDetached { @@ -34,6 +35,13 @@ impl<'repo> Commit<'repo> { pub fn detach(self) -> ObjectDetached { self.into() } + + /// Retrieve this instance's encoded data, leaving its own data empty. + /// + /// This method works around the immovability of members of this type. + pub fn take_data(&mut self) -> Vec<u8> { + std::mem::take(&mut self.data) + } } impl<'repo> Commit<'repo> { diff --git a/vendor/gix/src/object/impls.rs b/vendor/gix/src/object/impls.rs index 3453b1b3c..5d2ad8160 100644 --- a/vendor/gix/src/object/impls.rs +++ b/vendor/gix/src/object/impls.rs @@ -1,13 +1,13 @@ use std::convert::TryFrom; -use crate::{object, Commit, Object, ObjectDetached, Tag, Tree}; +use crate::{object, Blob, Commit, Object, ObjectDetached, Tag, Tree}; impl<'repo> From<Object<'repo>> for ObjectDetached { fn from(mut v: Object<'repo>) -> Self { ObjectDetached { id: v.id, kind: v.kind, - data: std::mem::take(&mut v.data), + data: steal_from_freelist(&mut v.data), } } } @@ -17,7 +17,7 @@ impl<'repo> From<Commit<'repo>> for ObjectDetached { ObjectDetached { id: v.id, kind: gix_object::Kind::Commit, - data: std::mem::take(&mut v.data), + data: steal_from_freelist(&mut v.data), } } } @@ -27,7 +27,27 @@ impl<'repo> From<Tag<'repo>> for ObjectDetached { ObjectDetached { id: v.id, kind: gix_object::Kind::Tag, - data: std::mem::take(&mut v.data), + data: steal_from_freelist(&mut v.data), + } + } +} + +impl<'repo> From<Blob<'repo>> for ObjectDetached { + fn from(mut v: Blob<'repo>) -> Self { + ObjectDetached { + id: v.id, + kind: gix_object::Kind::Blob, + data: steal_from_freelist(&mut v.data), + } + } +} + +impl<'repo> From<Tree<'repo>> for ObjectDetached { + fn from(mut v: Tree<'repo>) -> Self { + ObjectDetached { + id: v.id, + kind: gix_object::Kind::Tree, + data: steal_from_freelist(&mut v.data), } } } @@ -59,11 +79,11 @@ impl<'repo> TryFrom<Object<'repo>> for Commit<'repo> { type Error = Object<'repo>; fn try_from(mut value: Object<'repo>) -> Result<Self, Self::Error> { - let handle = value.repo; + let repo = value.repo; match value.kind { object::Kind::Commit => Ok(Commit { id: value.id, - repo: handle, + repo, data: steal_from_freelist(&mut value.data), }), _ => Err(value), @@ -75,11 +95,11 @@ impl<'repo> TryFrom<Object<'repo>> for Tag<'repo> { type Error = Object<'repo>; fn try_from(mut value: Object<'repo>) -> Result<Self, Self::Error> { - let handle = value.repo; + let repo = value.repo; match value.kind { object::Kind::Tag => Ok(Tag { id: value.id, - repo: handle, + repo, data: steal_from_freelist(&mut value.data), }), _ => Err(value), @@ -91,11 +111,27 @@ impl<'repo> TryFrom<Object<'repo>> for Tree<'repo> { type Error = Object<'repo>; fn try_from(mut value: Object<'repo>) -> Result<Self, Self::Error> { - let handle = value.repo; + let repo = value.repo; match value.kind { object::Kind::Tree => Ok(Tree { id: value.id, - repo: handle, + repo, + data: steal_from_freelist(&mut value.data), + }), + _ => Err(value), + } + } +} + +impl<'repo> TryFrom<Object<'repo>> for Blob<'repo> { + type Error = Object<'repo>; + + fn try_from(mut value: Object<'repo>) -> Result<Self, Self::Error> { + let repo = value.repo; + match value.kind { + object::Kind::Blob => Ok(Blob { + id: value.id, + repo, data: steal_from_freelist(&mut value.data), }), _ => Err(value), diff --git a/vendor/gix/src/object/mod.rs b/vendor/gix/src/object/mod.rs index d0a37db6c..ca2b07f8b 100644 --- a/vendor/gix/src/object/mod.rs +++ b/vendor/gix/src/object/mod.rs @@ -4,7 +4,7 @@ use std::convert::TryInto; use gix_hash::ObjectId; pub use gix_object::Kind; -use crate::{Commit, Id, Object, ObjectDetached, Tag, Tree}; +use crate::{Blob, Commit, Id, Object, ObjectDetached, Tag, Tree}; mod errors; pub(crate) mod cache { @@ -74,6 +74,14 @@ impl<'repo> Object<'repo> { } } + /// Transform this object into a blob, or panic if it is none. + pub fn into_blob(self) -> Blob<'repo> { + match self.try_into() { + Ok(tree) => tree, + Err(this) => panic!("Tried to use {} as tree, but was {}", this.id, this.kind), + } + } + /// Transform this object into a tree, or panic if it is none. pub fn into_tree(self) -> Tree<'repo> { match self.try_into() { @@ -124,6 +132,15 @@ impl<'repo> Object<'repo> { expected: gix_object::Kind::Tree, }) } + + /// Transform this object into a blob, or return it as part of the `Err` if it is no blob. + pub fn try_into_blob(self) -> Result<Blob<'repo>, try_into::Error> { + self.try_into().map_err(|this: Self| try_into::Error { + id: this.id, + actual: this.kind, + expected: gix_object::Kind::Blob, + }) + } } impl<'repo> Object<'repo> { diff --git a/vendor/gix/src/object/tag.rs b/vendor/gix/src/object/tag.rs index 77eaaa259..1a7a3de86 100644 --- a/vendor/gix/src/object/tag.rs +++ b/vendor/gix/src/object/tag.rs @@ -1,4 +1,4 @@ -use crate::{ext::ObjectIdExt, Tag}; +use crate::{ext::ObjectIdExt, ObjectDetached, Tag}; impl<'repo> Tag<'repo> { /// Decode the entire tag object and return it for accessing all tag information. @@ -24,3 +24,27 @@ impl<'repo> Tag<'repo> { gix_object::TagRefIter::from_bytes(&self.data).tagger() } } + +/// Remove Lifetime +impl Tag<'_> { + /// Create an owned instance of this object, copying our data in the process. + pub fn detached(&self) -> ObjectDetached { + ObjectDetached { + id: self.id, + kind: gix_object::Kind::Tag, + data: self.data.clone(), + } + } + + /// Sever the connection to the `Repository` and turn this instance into a standalone object. + pub fn detach(self) -> ObjectDetached { + self.into() + } + + /// Retrieve this instance's encoded data, leaving its own data empty. + /// + /// This method works around the immovability of members of this type. + pub fn take_data(&mut self) -> Vec<u8> { + std::mem::take(&mut self.data) + } +} diff --git a/vendor/gix/src/object/tree/mod.rs b/vendor/gix/src/object/tree/mod.rs index 5bf59a25c..e4dac24f8 100644 --- a/vendor/gix/src/object/tree/mod.rs +++ b/vendor/gix/src/object/tree/mod.rs @@ -4,7 +4,7 @@ pub use gix_object::tree::EntryMode; use gix_object::{bstr::BStr, TreeRefIter}; use gix_odb::FindExt; -use crate::{object::find, Id, Tree}; +use crate::{object::find, Id, ObjectDetached, Tree}; /// Initialization impl<'repo> Tree<'repo> { @@ -250,3 +250,27 @@ mod _impls { } } } + +/// Remove Lifetime +impl Tree<'_> { + /// Create an owned instance of this object, copying our data in the process. + pub fn detached(&self) -> ObjectDetached { + ObjectDetached { + id: self.id, + kind: gix_object::Kind::Tree, + data: self.data.clone(), + } + } + + /// Sever the connection to the `Repository` and turn this instance into a standalone object. + pub fn detach(self) -> ObjectDetached { + self.into() + } + + /// Retrieve this instance's encoded data, leaving its own data empty. + /// + /// This method works around the immovability of members of this type. + pub fn take_data(&mut self) -> Vec<u8> { + std::mem::take(&mut self.data) + } +} diff --git a/vendor/gix/src/reference/errors.rs b/vendor/gix/src/reference/errors.rs index a931b3974..ff3802e94 100644 --- a/vendor/gix/src/reference/errors.rs +++ b/vendor/gix/src/reference/errors.rs @@ -22,8 +22,8 @@ pub mod edit { /// pub mod peel { - /// The error returned by [`Reference::peel_to_id_in_place(…)`][crate::Reference::peel_to_id_in_place()] and - /// [`Reference::into_fully_peeled_id(…)`][crate::Reference::into_fully_peeled_id()]. + /// The error returned by [`Reference::peel_to_id_in_place(…)`](crate::Reference::peel_to_id_in_place()) and + /// [`Reference::into_fully_peeled_id(…)`](crate::Reference::into_fully_peeled_id()). #[derive(Debug, thiserror::Error)] #[allow(missing_docs)] pub enum Error { @@ -36,7 +36,7 @@ pub mod peel { /// pub mod head_id { - /// The error returned by [`Repository::head_id(…)`][crate::Repository::head_id()]. + /// The error returned by [`Repository::head_id(…)`](crate::Repository::head_id()). #[derive(Debug, thiserror::Error)] #[allow(missing_docs)] pub enum Error { @@ -51,7 +51,7 @@ pub mod head_id { /// pub mod head_commit { - /// The error returned by [`Repository::head_commit`(…)][crate::Repository::head_commit()]. + /// The error returned by [`Repository::head_commit`(…)](crate::Repository::head_commit()). #[derive(Debug, thiserror::Error)] #[allow(missing_docs)] pub enum Error { @@ -63,6 +63,21 @@ pub mod head_commit { } /// +pub mod head_tree_id { + /// The error returned by [`Repository::head_tree_id`(…)](crate::Repository::head_tree_id()). + #[derive(Debug, thiserror::Error)] + #[allow(missing_docs)] + pub enum Error { + #[error(transparent)] + Head(#[from] crate::reference::find::existing::Error), + #[error(transparent)] + PeelToCommit(#[from] crate::head::peel::to_commit::Error), + #[error(transparent)] + DecodeCommit(#[from] gix_object::decode::Error), + } +} + +/// pub mod find { /// pub mod existing { diff --git a/vendor/gix/src/reference/mod.rs b/vendor/gix/src/reference/mod.rs index e80057fb4..2d32f595d 100644 --- a/vendor/gix/src/reference/mod.rs +++ b/vendor/gix/src/reference/mod.rs @@ -10,7 +10,7 @@ pub mod iter; pub mod remote; mod errors; -pub use errors::{edit, find, head_commit, head_id, peel}; +pub use errors::{edit, find, head_commit, head_id, head_tree_id, peel}; use crate::ext::ObjectIdExt; diff --git a/vendor/gix/src/repository/cache.rs b/vendor/gix/src/repository/cache.rs index 7dcd844e6..03c2ff019 100644 --- a/vendor/gix/src/repository/cache.rs +++ b/vendor/gix/src/repository/cache.rs @@ -11,7 +11,7 @@ impl crate::Repository { pub fn object_cache_size(&mut self, bytes: impl Into<Option<usize>>) { let bytes = bytes.into(); match bytes { - Some(bytes) if bytes == 0 => self.objects.unset_object_cache(), + Some(0) => self.objects.unset_object_cache(), Some(bytes) => self .objects .set_object_cache(move || Box::new(crate::object::cache::MemoryCappedHashmap::new(bytes))), diff --git a/vendor/gix/src/repository/index.rs b/vendor/gix/src/repository/index.rs index a21b138a5..59666fc5f 100644 --- a/vendor/gix/src/repository/index.rs +++ b/vendor/gix/src/repository/index.rs @@ -55,6 +55,16 @@ impl crate::Repository { }) } + /// Return the shared worktree index if present, or return a new empty one which has an association to the place where the index would be. + pub fn index_or_empty(&self) -> Result<worktree::Index, worktree::open_index::Error> { + Ok(self.try_index()?.unwrap_or_else(|| { + worktree::Index::new(gix_fs::FileSnapshot::new(gix_index::File::from_state( + gix_index::State::new(self.object_hash()), + self.index_path(), + ))) + })) + } + /// Return a shared worktree index which is updated automatically if the in-memory snapshot has become stale as the underlying file /// on disk has changed, or `None` if no such file exists. /// diff --git a/vendor/gix/src/repository/location.rs b/vendor/gix/src/repository/location.rs index 5811e7bf9..8ee907ca9 100644 --- a/vendor/gix/src/repository/location.rs +++ b/vendor/gix/src/repository/location.rs @@ -37,6 +37,7 @@ impl crate::Repository { } /// Return the work tree containing all checked out files, if there is one. + #[doc(alias = "workdir", alias = "git2")] pub fn work_dir(&self) -> Option<&std::path::Path> { self.work_tree.as_deref() } diff --git a/vendor/gix/src/repository/object.rs b/vendor/gix/src/repository/object.rs index c156971d0..0b894939f 100644 --- a/vendor/gix/src/repository/object.rs +++ b/vendor/gix/src/repository/object.rs @@ -10,7 +10,7 @@ use gix_ref::{ }; use smallvec::SmallVec; -use crate::{commit, ext::ObjectIdExt, object, tag, Id, Object, Reference, Tree}; +use crate::{commit, ext::ObjectIdExt, object, tag, Blob, Id, Object, Reference, Tree}; /// Methods related to object creation. impl crate::Repository { @@ -26,7 +26,7 @@ impl crate::Repository { #[momo] pub fn find_object(&self, id: impl Into<ObjectId>) -> Result<Object<'_>, object::find::existing::Error> { let id = id.into(); - if id == gix_hash::ObjectId::empty_tree(self.object_hash()) { + if id == ObjectId::empty_tree(self.object_hash()) { return Ok(Object { id, kind: gix_object::Kind::Tree, @@ -46,7 +46,7 @@ impl crate::Repository { #[momo] pub fn find_header(&self, id: impl Into<ObjectId>) -> Result<gix_odb::find::Header, object::find::existing::Error> { let id = id.into(); - if id == gix_hash::ObjectId::empty_tree(self.object_hash()) { + if id == ObjectId::empty_tree(self.object_hash()) { return Ok(gix_odb::find::Header::Loose { kind: gix_object::Kind::Tree, size: 0, @@ -55,6 +55,25 @@ impl crate::Repository { self.objects.header(id) } + /// Return `true` if `id` exists in the object database. + /// + /// # Performance + /// + /// This method can be slow if the underlying [object database](crate::Repository::objects) has + /// an unsuitable [RefreshMode](gix_odb::store::RefreshMode) and `id` is not likely to exist. + /// Use [`repo.objects.refresh_never()`](gix_odb::store::Handle::refresh_never) to avoid expensive + /// IO-bound refreshes if an object wasn't found. + #[doc(alias = "exists", alias = "git2")] + #[momo] + pub fn has_object(&self, id: impl AsRef<gix_hash::oid>) -> bool { + let id = id.as_ref(); + if id == ObjectId::empty_tree(self.object_hash()) { + true + } else { + self.objects.contains(id) + } + } + /// Obtain information about an object without fully decoding it, or `None` if the object doesn't exist. /// /// Note that despite being cheaper than [`Self::try_find_object()`], there is still some effort traversing delta-chains. @@ -64,7 +83,7 @@ impl crate::Repository { id: impl Into<ObjectId>, ) -> Result<Option<gix_odb::find::Header>, object::find::Error> { let id = id.into(); - if id == gix_hash::ObjectId::empty_tree(self.object_hash()) { + if id == ObjectId::empty_tree(self.object_hash()) { return Ok(Some(gix_odb::find::Header::Loose { kind: gix_object::Kind::Tree, size: 0, @@ -77,7 +96,7 @@ impl crate::Repository { #[momo] pub fn try_find_object(&self, id: impl Into<ObjectId>) -> Result<Option<Object<'_>>, object::find::Error> { let id = id.into(); - if id == gix_hash::ObjectId::empty_tree(self.object_hash()) { + if id == ObjectId::empty_tree(self.object_hash()) { return Ok(Some(Object { id, kind: gix_object::Kind::Tree, @@ -236,7 +255,7 @@ impl crate::Repository { reference: FullName, message: &str, tree: ObjectId, - parents: SmallVec<[gix_hash::ObjectId; 1]>, + parents: SmallVec<[ObjectId; 1]>, ) -> Result<Id<'_>, commit::Error> { use gix_ref::{ transaction::{Change, RefEdit}, @@ -310,13 +329,25 @@ impl crate::Repository { self.commit_as(committer, author, reference, message, tree, parents) } - /// Return an empty tree object, suitable for [getting changes](crate::Tree::changes()). + /// Return an empty tree object, suitable for [getting changes](Tree::changes()). /// - /// Note that it is special and doesn't physically exist in the object database even though it can be returned. + /// Note that the returned object is special and doesn't necessarily physically exist in the object database. /// This means that this object can be used in an uninitialized, empty repository which would report to have no objects at all. pub fn empty_tree(&self) -> Tree<'_> { - self.find_object(gix_hash::ObjectId::empty_tree(self.object_hash())) + self.find_object(ObjectId::empty_tree(self.object_hash())) .expect("always present") .into_tree() } + + /// Return an empty blob object. + /// + /// Note that the returned object is special and doesn't necessarily physically exist in the object database. + /// This means that this object can be used in an uninitialized, empty repository which would report to have no objects at all. + pub fn empty_blob(&self) -> Blob<'_> { + Blob { + id: gix_hash::ObjectId::empty_blob(self.object_hash()), + data: Vec::new(), + repo: self, + } + } } diff --git a/vendor/gix/src/repository/reference.rs b/vendor/gix/src/repository/reference.rs index 5a14c60b5..e57ca63c0 100644 --- a/vendor/gix/src/repository/reference.rs +++ b/vendor/gix/src/repository/reference.rs @@ -212,6 +212,15 @@ impl crate::Repository { Ok(self.head()?.peel_to_commit_in_place()?) } + /// Return the tree id the `HEAD` reference currently points to after peeling it fully. + /// + /// Note that this may fail for various reasons, most notably because the repository + /// is freshly initialized and doesn't have any commits yet. It could also fail if the + /// head does not point to a commit. + pub fn head_tree_id(&self) -> Result<crate::Id<'_>, reference::head_tree_id::Error> { + Ok(self.head()?.peel_to_commit_in_place()?.tree_id()?) + } + /// Find the reference with the given partial or full `name`, like `main`, `HEAD`, `heads/branch` or `origin/other`, /// or return an error if it wasn't found. /// diff --git a/vendor/gix/src/types.rs b/vendor/gix/src/types.rs index 0739cdd25..0dc81abae 100644 --- a/vendor/gix/src/types.rs +++ b/vendor/gix/src/types.rs @@ -31,6 +31,7 @@ pub struct Id<'r> { } /// A decoded object with a reference to its owning repository. +#[derive(Clone)] pub struct Object<'repo> { /// The id of the object pub id: ObjectId, @@ -47,7 +48,24 @@ impl<'a> Drop for Object<'a> { } } +/// A blob along with access to its owning repository. +#[derive(Clone)] +pub struct Blob<'repo> { + /// The id of the tree + pub id: ObjectId, + /// The blob's data. + pub data: Vec<u8>, + pub(crate) repo: &'repo Repository, +} + +impl<'a> Drop for Blob<'a> { + fn drop(&mut self) { + self.repo.reuse_buffer(&mut self.data); + } +} + /// A decoded tree object with access to its owning repository. +#[derive(Clone)] pub struct Tree<'repo> { /// The id of the tree pub id: ObjectId, @@ -63,6 +81,7 @@ impl<'a> Drop for Tree<'a> { } /// A decoded tag object with access to its owning repository. +#[derive(Clone)] pub struct Tag<'repo> { /// The id of the tree pub id: ObjectId, @@ -78,6 +97,7 @@ impl<'a> Drop for Tag<'a> { } /// A decoded commit object with access to its owning repository. +#[derive(Clone)] pub struct Commit<'repo> { /// The id of the commit pub id: ObjectId, |