summaryrefslogtreecommitdiffstats
path: root/vendor/gix-pack/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
commit9918693037dce8aa4bb6f08741b6812923486c18 (patch)
tree21d2b40bec7e6a7ea664acee056eb3d08e15a1cf /vendor/gix-pack/src
parentReleasing progress-linux version 1.75.0+dfsg1-5~progress7.99u1. (diff)
downloadrustc-9918693037dce8aa4bb6f08741b6812923486c18.tar.xz
rustc-9918693037dce8aa4bb6f08741b6812923486c18.zip
Merging upstream version 1.76.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/gix-pack/src')
-rw-r--r--vendor/gix-pack/src/bundle/write/mod.rs22
-rw-r--r--vendor/gix-pack/src/cache/delta/traverse/mod.rs33
-rw-r--r--vendor/gix-pack/src/cache/delta/traverse/resolve.rs82
-rw-r--r--vendor/gix-pack/src/cache/delta/traverse/util.rs81
-rw-r--r--vendor/gix-pack/src/data/file/decode/header.rs3
-rw-r--r--vendor/gix-pack/src/data/file/verify.rs3
-rw-r--r--vendor/gix-pack/src/data/input/lookup_ref_delta_objects.rs16
-rw-r--r--vendor/gix-pack/src/data/output/count/objects/mod.rs132
-rw-r--r--vendor/gix-pack/src/data/output/count/objects/tree.rs12
-rw-r--r--vendor/gix-pack/src/data/output/count/objects/types.rs2
-rw-r--r--vendor/gix-pack/src/data/output/entry/iter_from_counts.rs16
-rw-r--r--vendor/gix-pack/src/find.rs54
-rw-r--r--vendor/gix-pack/src/find_traits.rs47
-rw-r--r--vendor/gix-pack/src/index/encode.rs4
-rw-r--r--vendor/gix-pack/src/index/traverse/with_index.rs3
-rw-r--r--vendor/gix-pack/src/index/traverse/with_lookup.rs3
-rw-r--r--vendor/gix-pack/src/index/verify.rs25
-rw-r--r--vendor/gix-pack/src/index/write/mod.rs3
-rwxr-xr-xvendor/gix-pack/src/lib.rs6
19 files changed, 279 insertions, 268 deletions
diff --git a/vendor/gix-pack/src/bundle/write/mod.rs b/vendor/gix-pack/src/bundle/write/mod.rs
index 8983cb92f..9ddd1b9d3 100644
--- a/vendor/gix-pack/src/bundle/write/mod.rs
+++ b/vendor/gix-pack/src/bundle/write/mod.rs
@@ -21,10 +21,6 @@ pub use types::{Options, Outcome};
use crate::bundle::write::types::SharedTempFile;
-type ThinPackLookupFn = Box<dyn for<'a> FnMut(gix_hash::ObjectId, &'a mut Vec<u8>) -> Option<gix_object::Data<'a>>>;
-type ThinPackLookupFnSend =
- Box<dyn for<'a> FnMut(gix_hash::ObjectId, &'a mut Vec<u8>) -> Option<gix_object::Data<'a>> + Send + 'static>;
-
/// The progress ids used in [`write_to_directory()`][crate::Bundle::write_to_directory()].
///
/// Use this information to selectively extract the progress of interest in case the parent application has custom visualization.
@@ -54,7 +50,7 @@ impl crate::Bundle {
///
/// * `progress` provides detailed progress information which can be discarded with [`gix_features::progress::Discard`].
/// * `should_interrupt` is checked regularly and when true, the whole operation will stop.
- /// * `thin_pack_base_object_lookup_fn` If set, we expect to see a thin-pack with objects that reference their base object by object id which is
+ /// * `thin_pack_base_object_lookup` If set, we expect to see a thin-pack with objects that reference their base object by object id which is
/// expected to exist in the object database the bundle is contained within.
/// `options` further configure how the task is performed.
///
@@ -68,7 +64,7 @@ impl crate::Bundle {
directory: Option<&Path>,
progress: &mut dyn DynNestedProgress,
should_interrupt: &AtomicBool,
- thin_pack_base_object_lookup_fn: Option<ThinPackLookupFn>,
+ thin_pack_base_object_lookup: Option<impl gix_object::Find>,
options: Options,
) -> Result<Outcome, Error> {
let _span = gix_features::trace::coarse!("gix_pack::Bundle::write_to_directory()");
@@ -90,8 +86,8 @@ impl crate::Bundle {
let (pack_entries_iter, pack_version): (
Box<dyn Iterator<Item = Result<data::input::Entry, data::input::Error>>>,
_,
- ) = match thin_pack_base_object_lookup_fn {
- Some(thin_pack_lookup_fn) => {
+ ) = match thin_pack_base_object_lookup {
+ Some(thin_pack_lookup) => {
let pack = interrupt::Read {
inner: pack,
should_interrupt,
@@ -104,7 +100,7 @@ impl crate::Bundle {
data::input::EntryDataMode::KeepAndCrc32,
object_hash,
)?,
- thin_pack_lookup_fn,
+ thin_pack_lookup,
);
let pack_version = pack_entries_iter.inner.version();
let pack_entries_iter = data::input::EntriesToBytesIter::new(
@@ -178,7 +174,7 @@ impl crate::Bundle {
directory: Option<impl AsRef<Path>>,
progress: &mut dyn DynNestedProgress,
should_interrupt: &'static AtomicBool,
- thin_pack_base_object_lookup_fn: Option<ThinPackLookupFnSend>,
+ thin_pack_base_object_lookup: Option<impl gix_object::Find + Send + 'static>,
options: Options,
) -> Result<Outcome, Error> {
let _span = gix_features::trace::coarse!("gix_pack::Bundle::write_to_directory_eagerly()");
@@ -198,8 +194,8 @@ impl crate::Bundle {
let (pack_entries_iter, pack_version): (
Box<dyn Iterator<Item = Result<data::input::Entry, data::input::Error>> + Send + 'static>,
_,
- ) = match thin_pack_base_object_lookup_fn {
- Some(thin_pack_lookup_fn) => {
+ ) = match thin_pack_base_object_lookup {
+ Some(thin_pack_lookup) => {
let pack = interrupt::Read {
inner: pack,
should_interrupt,
@@ -212,7 +208,7 @@ impl crate::Bundle {
data::input::EntryDataMode::KeepAndCrc32,
object_hash,
)?,
- thin_pack_lookup_fn,
+ thin_pack_lookup,
);
let pack_kind = pack_entries_iter.inner.version();
(Box::new(pack_entries_iter), pack_kind)
diff --git a/vendor/gix-pack/src/cache/delta/traverse/mod.rs b/vendor/gix-pack/src/cache/delta/traverse/mod.rs
index 0598cf92e..ee3481627 100644
--- a/vendor/gix-pack/src/cache/delta/traverse/mod.rs
+++ b/vendor/gix-pack/src/cache/delta/traverse/mod.rs
@@ -1,15 +1,14 @@
use std::sync::atomic::{AtomicBool, Ordering};
-use gix_features::progress::DynNestedProgress;
use gix_features::{
parallel::in_parallel_with_slice,
- progress::{self, Progress},
+ progress::{self, DynNestedProgress, Progress},
threading,
threading::{Mutable, OwnShared},
};
use crate::{
- cache::delta::{traverse::util::ItemSliceSend, Item, Tree},
+ cache::delta::{traverse::util::ItemSliceSync, Item, Tree},
data::EntryRange,
};
@@ -130,32 +129,26 @@ where
};
size_progress.init(None, progress::bytes());
let size_counter = size_progress.counter();
- let child_items = self.child_items.as_mut_slice();
let object_progress = OwnShared::new(Mutable::new(object_progress));
let start = std::time::Instant::now();
+ let child_items = ItemSliceSync::new(&mut self.child_items);
+ let child_items = &child_items;
in_parallel_with_slice(
&mut self.root_items,
thread_limit,
{
- let child_items = ItemSliceSend(std::ptr::slice_from_raw_parts_mut(
- child_items.as_mut_ptr(),
- child_items.len(),
- ));
{
let object_progress = object_progress.clone();
- move |thread_index| {
- let _ = &child_items;
- resolve::State {
- delta_bytes: Vec::<u8>::with_capacity(4096),
- fully_resolved_delta_bytes: Vec::<u8>::with_capacity(4096),
- progress: Box::new(
- threading::lock(&object_progress).add_child(format!("thread {thread_index}")),
- ),
- resolve: resolve.clone(),
- modify_base: inspect_object.clone(),
- child_items: child_items.clone(),
- }
+ move |thread_index| resolve::State {
+ delta_bytes: Vec::<u8>::with_capacity(4096),
+ fully_resolved_delta_bytes: Vec::<u8>::with_capacity(4096),
+ progress: Box::new(
+ threading::lock(&object_progress).add_child(format!("thread {thread_index}")),
+ ),
+ resolve: resolve.clone(),
+ modify_base: inspect_object.clone(),
+ child_items,
}
}
},
diff --git a/vendor/gix-pack/src/cache/delta/traverse/resolve.rs b/vendor/gix-pack/src/cache/delta/traverse/resolve.rs
index daf6f273e..26a182485 100644
--- a/vendor/gix-pack/src/cache/delta/traverse/resolve.rs
+++ b/vendor/gix-pack/src/cache/delta/traverse/resolve.rs
@@ -7,30 +7,81 @@ use gix_features::{progress::Progress, threading, zlib};
use crate::{
cache::delta::{
- traverse::{
- util::{ItemSliceSend, Node},
- Context, Error,
- },
+ traverse::{util::ItemSliceSync, Context, Error},
Item,
},
data,
data::EntryRange,
};
-pub(crate) struct State<F, MBFN, T: Send> {
+mod node {
+ use crate::cache::delta::{traverse::util::ItemSliceSync, Item};
+
+ /// An item returned by `iter_root_chunks`, allowing access to the `data` stored alongside nodes in a [`Tree`].
+ pub(crate) struct Node<'a, T: Send> {
+ item: &'a mut Item<T>,
+ child_items: &'a ItemSliceSync<'a, Item<T>>,
+ }
+
+ impl<'a, T: Send> Node<'a, T> {
+ /// SAFETY: The child_items must be unique among between users of the `ItemSliceSync`.
+ #[allow(unsafe_code)]
+ pub(crate) unsafe fn new(item: &'a mut Item<T>, child_items: &'a ItemSliceSync<'a, Item<T>>) -> Self {
+ Node { item, child_items }
+ }
+ }
+
+ impl<'a, T: Send> Node<'a, T> {
+ /// Returns the offset into the pack at which the `Node`s data is located.
+ pub fn offset(&self) -> u64 {
+ self.item.offset
+ }
+
+ /// Returns the slice into the data pack at which the pack entry is located.
+ pub fn entry_slice(&self) -> crate::data::EntryRange {
+ self.item.offset..self.item.next_offset
+ }
+
+ /// Returns the node data associated with this node.
+ pub fn data(&mut self) -> &mut T {
+ &mut self.item.data
+ }
+
+ /// Returns true if this node has children, e.g. is not a leaf in the tree.
+ pub fn has_children(&self) -> bool {
+ !self.item.children.is_empty()
+ }
+
+ /// Transform this `Node` into an iterator over its children.
+ ///
+ /// Children are `Node`s referring to pack entries whose base object is this pack entry.
+ pub fn into_child_iter(self) -> impl Iterator<Item = Node<'a, T>> + 'a {
+ let children = self.child_items;
+ // SAFETY: The index is a valid index into the children array.
+ // SAFETY: The resulting mutable pointer cannot be yielded by any other node.
+ #[allow(unsafe_code)]
+ self.item.children.iter().map(move |&index| Node {
+ item: unsafe { children.get_mut(index as usize) },
+ child_items: children,
+ })
+ }
+ }
+}
+
+pub(crate) struct State<'items, F, MBFN, T: Send> {
pub delta_bytes: Vec<u8>,
pub fully_resolved_delta_bytes: Vec<u8>,
pub progress: Box<dyn Progress>,
pub resolve: F,
pub modify_base: MBFN,
- pub child_items: ItemSliceSend<Item<T>>,
+ pub child_items: &'items ItemSliceSync<'items, Item<T>>,
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn deltas<T, F, MBFN, E, R>(
objects: gix_features::progress::StepShared,
size: gix_features::progress::StepShared,
- node: &mut Item<T>,
+ item: &mut Item<T>,
State {
delta_bytes,
fully_resolved_delta_bytes,
@@ -38,7 +89,7 @@ pub(crate) fn deltas<T, F, MBFN, E, R>(
resolve,
modify_base,
child_items,
- }: &mut State<F, MBFN, T>,
+ }: &mut State<'_, F, MBFN, T>,
resolve_data: &R,
hash_len: usize,
threads_left: &AtomicIsize,
@@ -67,13 +118,10 @@ where
// each node is a base, and its children always start out as deltas which become a base after applying them.
// These will be pushed onto our stack until all are processed
let root_level = 0;
- let mut nodes: Vec<_> = vec![(
- root_level,
- Node {
- item: node,
- child_items: child_items.clone(),
- },
- )];
+ // SAFETY: The child items are unique
+ #[allow(unsafe_code)]
+ let root_node = unsafe { node::Node::new(item, child_items) };
+ let mut nodes: Vec<_> = vec![(root_level, root_node)];
while let Some((level, mut base)) = nodes.pop() {
if should_interrupt.load(Ordering::Relaxed) {
return Err(Error::Interrupted);
@@ -186,13 +234,13 @@ where
/// system. Since this thread will take a controlling function, we may spawn one more than that. In threaded mode, we will finish
/// all remaining work.
#[allow(clippy::too_many_arguments)]
-pub(crate) fn deltas_mt<T, F, MBFN, E, R>(
+fn deltas_mt<T, F, MBFN, E, R>(
mut threads_to_create: isize,
decompressed_bytes_by_pack_offset: BTreeMap<u64, (data::Entry, u64, Vec<u8>)>,
objects: gix_features::progress::StepShared,
size: gix_features::progress::StepShared,
progress: &dyn Progress,
- nodes: Vec<(u16, Node<'_, T>)>,
+ nodes: Vec<(u16, node::Node<'_, T>)>,
resolve: F,
resolve_data: &R,
modify_base: MBFN,
diff --git a/vendor/gix-pack/src/cache/delta/traverse/util.rs b/vendor/gix-pack/src/cache/delta/traverse/util.rs
index 1b7015351..5f09b918d 100644
--- a/vendor/gix-pack/src/cache/delta/traverse/util.rs
+++ b/vendor/gix-pack/src/cache/delta/traverse/util.rs
@@ -1,65 +1,36 @@
-use crate::cache::delta::Item;
+use std::marker::PhantomData;
-pub struct ItemSliceSend<T>(pub *mut [T])
-where
- T: Send;
-
-/// SAFETY: This would be unsafe if this would ever be abused, but it's used internally and only in a way that assure that the pointers
-/// don't violate aliasing rules.
-impl<T> Clone for ItemSliceSend<T>
+pub(crate) struct ItemSliceSync<'a, T>
where
T: Send,
{
- fn clone(&self) -> Self {
- ItemSliceSend(self.0)
- }
-}
-
-// SAFETY: T is `Send`, and we only ever access one T at a time. And, ptrs need that assurance, I wonder if it's always right.
-#[allow(unsafe_code)]
-unsafe impl<T> Send for ItemSliceSend<T> where T: Send {}
-
-/// An item returned by `iter_root_chunks`, allowing access to the `data` stored alongside nodes in a [`Tree`].
-pub struct Node<'a, T: Send> {
- pub item: &'a mut Item<T>,
- pub child_items: ItemSliceSend<Item<T>>,
+ items: *mut T,
+ phantom: PhantomData<&'a T>,
}
-impl<'a, T: Send> Node<'a, T> {
- /// Returns the offset into the pack at which the `Node`s data is located.
- pub fn offset(&self) -> u64 {
- self.item.offset
- }
-
- /// Returns the slice into the data pack at which the pack entry is located.
- pub fn entry_slice(&self) -> crate::data::EntryRange {
- self.item.offset..self.item.next_offset
- }
-
- /// Returns the node data associated with this node.
- pub fn data(&mut self) -> &mut T {
- &mut self.item.data
- }
-
- /// Returns true if this node has children, e.g. is not a leaf in the tree.
- pub fn has_children(&self) -> bool {
- !self.item.children.is_empty()
+impl<'a, T> ItemSliceSync<'a, T>
+where
+ T: Send,
+{
+ pub fn new(items: &'a mut [T]) -> Self {
+ ItemSliceSync {
+ items: items.as_mut_ptr(),
+ phantom: PhantomData,
+ }
}
- /// Transform this `Node` into an iterator over its children.
- ///
- /// Children are `Node`s referring to pack entries whose base object is this pack entry.
- pub fn into_child_iter(self) -> impl Iterator<Item = Node<'a, T>> + 'a {
- let children = self.child_items;
- self.item.children.iter().map(move |&index| {
- // SAFETY: The children array is alive by the 'a lifetime.
- // SAFETY: The index is a valid index into the children array.
- // SAFETY: The resulting mutable pointer cannot be yielded by any other node.
- #[allow(unsafe_code)]
- Node {
- item: &mut unsafe { &mut *children.0 }[index as usize],
- child_items: children.clone(),
- }
- })
+ /// SAFETY: The index must point into the slice and must not be reused concurrently.
+ #[allow(unsafe_code)]
+ pub unsafe fn get_mut(&self, index: usize) -> &'a mut T {
+ // SAFETY: The children array is alive by the 'a lifetime.
+ unsafe { &mut *self.items.add(index) }
}
}
+
+// SAFETY: T is `Send`, and we only use the pointer for creating new pointers.
+#[allow(unsafe_code)]
+unsafe impl<T> Send for ItemSliceSync<'_, T> where T: Send {}
+// SAFETY: T is `Send`, and as long as the user follows the contract of
+// `get_mut()`, we only ever access one T at a time.
+#[allow(unsafe_code)]
+unsafe impl<T> Sync for ItemSliceSync<'_, T> where T: Send {}
diff --git a/vendor/gix-pack/src/data/file/decode/header.rs b/vendor/gix-pack/src/data/file/decode/header.rs
index 3a6e40f8a..fb23f482d 100644
--- a/vendor/gix-pack/src/data/file/decode/header.rs
+++ b/vendor/gix-pack/src/data/file/decode/header.rs
@@ -1,8 +1,9 @@
+use gix_features::zlib;
+
use crate::{
data,
data::{delta, file::decode::Error, File},
};
-use gix_features::zlib;
/// A return value of a resolve function, which given an [`ObjectId`][gix_hash::ObjectId] determines where an object can be found.
#[derive(Debug, PartialEq, Eq, Hash, Ord, PartialOrd, Clone)]
diff --git a/vendor/gix-pack/src/data/file/verify.rs b/vendor/gix-pack/src/data/file/verify.rs
index 11cec041d..76d47de0b 100644
--- a/vendor/gix-pack/src/data/file/verify.rs
+++ b/vendor/gix-pack/src/data/file/verify.rs
@@ -1,6 +1,7 @@
-use gix_features::progress::Progress;
use std::sync::atomic::AtomicBool;
+use gix_features::progress::Progress;
+
use crate::data::File;
///
diff --git a/vendor/gix-pack/src/data/input/lookup_ref_delta_objects.rs b/vendor/gix-pack/src/data/input/lookup_ref_delta_objects.rs
index 60f686d3a..f6036e20f 100644
--- a/vendor/gix-pack/src/data/input/lookup_ref_delta_objects.rs
+++ b/vendor/gix-pack/src/data/input/lookup_ref_delta_objects.rs
@@ -5,10 +5,10 @@ use gix_hash::ObjectId;
use crate::data::{entry::Header, input};
/// An iterator to resolve thin packs on the fly.
-pub struct LookupRefDeltaObjectsIter<I, LFn> {
+pub struct LookupRefDeltaObjectsIter<I, Find> {
/// The inner iterator whose entries we will resolve.
pub inner: I,
- lookup: LFn,
+ lookup: Find,
/// The cached delta to provide next time we are called, it's the delta to go with the base we just resolved in its place.
next_delta: Option<input::Entry>,
/// Fuse to stop iteration after first missing object.
@@ -21,14 +21,14 @@ pub struct LookupRefDeltaObjectsIter<I, LFn> {
buf: Vec<u8>,
}
-impl<I, LFn> LookupRefDeltaObjectsIter<I, LFn>
+impl<I, Find> LookupRefDeltaObjectsIter<I, Find>
where
I: Iterator<Item = Result<input::Entry, input::Error>>,
- LFn: for<'a> FnMut(ObjectId, &'a mut Vec<u8>) -> Option<gix_object::Data<'a>>,
+ Find: gix_object::Find,
{
/// Create a new instance wrapping `iter` and using `lookup` as function to retrieve objects that will serve as bases
/// for ref deltas seen while traversing `iter`.
- pub fn new(iter: I, lookup: LFn) -> Self {
+ pub fn new(iter: I, lookup: Find) -> Self {
LookupRefDeltaObjectsIter {
inner: iter,
lookup,
@@ -75,10 +75,10 @@ where
}
}
-impl<I, LFn> Iterator for LookupRefDeltaObjectsIter<I, LFn>
+impl<I, Find> Iterator for LookupRefDeltaObjectsIter<I, Find>
where
I: Iterator<Item = Result<input::Entry, input::Error>>,
- LFn: for<'a> FnMut(ObjectId, &'a mut Vec<u8>) -> Option<gix_object::Data<'a>>,
+ Find: gix_object::Find,
{
type Item = Result<input::Entry, input::Error>;
@@ -94,7 +94,7 @@ where
Header::RefDelta { base_id } => {
match self.inserted_entry_length_at_offset.iter().rfind(|e| e.oid == base_id) {
None => {
- let base_entry = match (self.lookup)(base_id, &mut self.buf) {
+ let base_entry = match self.lookup.try_find(&base_id, &mut self.buf).ok()? {
Some(obj) => {
let current_pack_offset = entry.pack_offset;
let mut entry = match input::Entry::from_data_obj(&obj, 0) {
diff --git a/vendor/gix-pack/src/data/output/count/objects/mod.rs b/vendor/gix-pack/src/data/output/count/objects/mod.rs
index 24810577c..34e922e9b 100644
--- a/vendor/gix-pack/src/data/output/count/objects/mod.rs
+++ b/vendor/gix-pack/src/data/output/count/objects/mod.rs
@@ -114,10 +114,13 @@ pub fn objects_unthreaded(
}
mod expand {
- use std::sync::atomic::{AtomicBool, Ordering};
+ use std::{
+ cell::RefCell,
+ sync::atomic::{AtomicBool, Ordering},
+ };
use gix_hash::{oid, ObjectId};
- use gix_object::{CommitRefIter, TagRefIter};
+ use gix_object::{CommitRefIter, Data, TagRefIter};
use super::{
tree,
@@ -206,24 +209,15 @@ mod expand {
let objects_ref = if parent_commit_ids.is_empty() {
traverse_delegate.clear();
+ let objects = ExpandedCountingObjects::new(db, out, objects);
gix_traverse::tree::breadthfirst(
current_tree_iter,
&mut tree_traversal_state,
- |oid, buf| {
- stats.decoded_objects += 1;
- match db.find(oid, buf).ok() {
- Some((obj, location)) => {
- objects.fetch_add(1, Ordering::Relaxed);
- stats.expanded_objects += 1;
- out.push(output::Count::from_data(oid, location));
- obj.try_into_tree_iter()
- }
- None => None,
- }
- },
+ &objects,
&mut traverse_delegate,
)
.map_err(Error::TreeTraverse)?;
+ out = objects.dissolve(stats);
&traverse_delegate.non_trees
} else {
for commit_id in &parent_commit_ids {
@@ -252,17 +246,16 @@ mod expand {
};
changes_delegate.clear();
+ let objects = CountingObjects::new(db);
gix_diff::tree::Changes::from(Some(parent_tree))
.needed_to_obtain(
- current_tree_iter.clone(),
+ current_tree_iter,
&mut tree_diff_state,
- |oid, buf| {
- stats.decoded_objects += 1;
- db.find_tree_iter(oid, buf).map(|t| t.0)
- },
+ &objects,
&mut changes_delegate,
)
.map_err(Error::TreeChanges)?;
+ stats.decoded_objects += objects.into_count();
}
&changes_delegate.objects
};
@@ -283,24 +276,17 @@ mod expand {
match obj.0.kind {
Tree => {
traverse_delegate.clear();
- gix_traverse::tree::breadthfirst(
- gix_object::TreeRefIter::from_bytes(obj.0.data),
- &mut tree_traversal_state,
- |oid, buf| {
- stats.decoded_objects += 1;
- match db.find(oid, buf).ok() {
- Some((obj, location)) => {
- objects.fetch_add(1, Ordering::Relaxed);
- stats.expanded_objects += 1;
- out.push(output::Count::from_data(oid, location));
- obj.try_into_tree_iter()
- }
- None => None,
- }
- },
- &mut traverse_delegate,
- )
- .map_err(Error::TreeTraverse)?;
+ {
+ let objects = ExpandedCountingObjects::new(db, out, objects);
+ gix_traverse::tree::breadthfirst(
+ gix_object::TreeRefIter::from_bytes(obj.0.data),
+ &mut tree_traversal_state,
+ &objects,
+ &mut traverse_delegate,
+ )
+ .map_err(Error::TreeTraverse)?;
+ out = objects.dissolve(stats);
+ }
for id in &traverse_delegate.non_trees {
out.push(id_to_count(db, buf1, id, objects, stats, allow_pack_lookups));
}
@@ -374,4 +360,76 @@ mod expand {
},
}
}
+
+ struct CountingObjects<'a> {
+ decoded_objects: std::cell::RefCell<usize>,
+ objects: &'a dyn crate::Find,
+ }
+
+ impl<'a> CountingObjects<'a> {
+ fn new(objects: &'a dyn crate::Find) -> Self {
+ Self {
+ decoded_objects: Default::default(),
+ objects,
+ }
+ }
+
+ fn into_count(self) -> usize {
+ self.decoded_objects.into_inner()
+ }
+ }
+
+ impl gix_object::Find for CountingObjects<'_> {
+ fn try_find<'a>(&self, id: &oid, buffer: &'a mut Vec<u8>) -> Result<Option<Data<'a>>, gix_object::find::Error> {
+ let res = Ok(self.objects.try_find(id, buffer)?.map(|t| t.0));
+ *self.decoded_objects.borrow_mut() += 1;
+ res
+ }
+ }
+
+ struct ExpandedCountingObjects<'a> {
+ decoded_objects: std::cell::RefCell<usize>,
+ expanded_objects: std::cell::RefCell<usize>,
+ out: std::cell::RefCell<Vec<output::Count>>,
+ objects_count: &'a gix_features::progress::AtomicStep,
+ objects: &'a dyn crate::Find,
+ }
+
+ impl<'a> ExpandedCountingObjects<'a> {
+ fn new(
+ objects: &'a dyn crate::Find,
+ out: Vec<output::Count>,
+ objects_count: &'a gix_features::progress::AtomicStep,
+ ) -> Self {
+ Self {
+ decoded_objects: Default::default(),
+ expanded_objects: Default::default(),
+ out: RefCell::new(out),
+ objects_count,
+ objects,
+ }
+ }
+
+ fn dissolve(self, stats: &mut Outcome) -> Vec<output::Count> {
+ stats.decoded_objects += self.decoded_objects.into_inner();
+ stats.expanded_objects += self.expanded_objects.into_inner();
+ self.out.into_inner()
+ }
+ }
+
+ impl gix_object::Find for ExpandedCountingObjects<'_> {
+ fn try_find<'a>(&self, id: &oid, buffer: &'a mut Vec<u8>) -> Result<Option<Data<'a>>, gix_object::find::Error> {
+ let maybe_obj = self.objects.try_find(id, buffer)?;
+ *self.decoded_objects.borrow_mut() += 1;
+ match maybe_obj {
+ None => Ok(None),
+ Some((obj, location)) => {
+ self.objects_count.fetch_add(1, Ordering::Relaxed);
+ *self.expanded_objects.borrow_mut() += 1;
+ self.out.borrow_mut().push(output::Count::from_data(id, location));
+ Ok(Some(obj))
+ }
+ }
+ }
+ }
}
diff --git a/vendor/gix-pack/src/data/output/count/objects/tree.rs b/vendor/gix-pack/src/data/output/count/objects/tree.rs
index d3f4f6b9a..824b48062 100644
--- a/vendor/gix-pack/src/data/output/count/objects/tree.rs
+++ b/vendor/gix-pack/src/data/output/count/objects/tree.rs
@@ -4,7 +4,7 @@ pub mod changes {
Visit,
};
use gix_hash::ObjectId;
- use gix_object::{bstr::BStr, tree::EntryMode};
+ use gix_object::bstr::BStr;
use crate::data::output::count::objects_impl::util::InsertImmutable;
@@ -43,7 +43,7 @@ pub mod changes {
fn visit(&mut self, change: Change) -> Action {
match change {
Change::Addition { oid, entry_mode } | Change::Modification { oid, entry_mode, .. } => {
- if entry_mode == EntryMode::Commit {
+ if entry_mode.is_commit() {
return Action::Continue;
}
let inserted = self.all_seen.insert(oid);
@@ -60,10 +60,7 @@ pub mod changes {
pub mod traverse {
use gix_hash::ObjectId;
- use gix_object::{
- bstr::BStr,
- tree::{EntryMode, EntryRef},
- };
+ use gix_object::{bstr::BStr, tree::EntryRef};
use gix_traverse::tree::{visit::Action, Visit};
use crate::data::output::count::objects_impl::util::InsertImmutable;
@@ -110,8 +107,7 @@ pub mod traverse {
}
fn visit_nontree(&mut self, entry: &EntryRef<'_>) -> Action {
- if entry.mode == EntryMode::Commit {
- // links don't have a representation
+ if entry.mode.is_commit() {
return Action::Continue;
}
let inserted = self.all_seen.insert(entry.oid.to_owned());
diff --git a/vendor/gix-pack/src/data/output/count/objects/types.rs b/vendor/gix-pack/src/data/output/count/objects/types.rs
index 4b9ecea20..15e395018 100644
--- a/vendor/gix-pack/src/data/output/count/objects/types.rs
+++ b/vendor/gix-pack/src/data/output/count/objects/types.rs
@@ -84,7 +84,7 @@ pub enum Error {
#[error(transparent)]
CommitDecode(gix_object::decode::Error),
#[error(transparent)]
- FindExisting(#[from] crate::find::existing::Error),
+ FindExisting(#[from] gix_object::find::existing::Error),
#[error(transparent)]
InputIteration(Box<dyn std::error::Error + Send + Sync + 'static>),
#[error(transparent)]
diff --git a/vendor/gix-pack/src/data/output/entry/iter_from_counts.rs b/vendor/gix-pack/src/data/output/entry/iter_from_counts.rs
index 2bebf5b20..87caf039c 100644
--- a/vendor/gix-pack/src/data/output/entry/iter_from_counts.rs
+++ b/vendor/gix-pack/src/data/output/entry/iter_from_counts.rs
@@ -1,8 +1,14 @@
pub(crate) mod function {
use std::{cmp::Ordering, sync::Arc};
- use gix_features::progress::prodash::{Count, DynNestedProgress};
- use gix_features::{parallel, parallel::SequenceId, progress::Progress};
+ use gix_features::{
+ parallel,
+ parallel::SequenceId,
+ progress::{
+ prodash::{Count, DynNestedProgress},
+ Progress,
+ },
+ };
use super::{reduce, util, Error, Mode, Options, Outcome, ProgressId};
use crate::data::output;
@@ -204,7 +210,7 @@ pub(crate) mod function {
stats.objects_copied_from_pack += 1;
entry
}
- None => match db.try_find(&count.id, buf).map_err(Error::FindExisting)? {
+ None => match db.try_find(&count.id, buf).map_err(Error::Find)? {
Some((obj, _location)) => {
stats.decoded_and_recompressed_objects += 1;
output::Entry::from_data(count, &obj)
@@ -216,7 +222,7 @@ pub(crate) mod function {
},
}
}
- None => match db.try_find(&count.id, buf).map_err(Error::FindExisting)? {
+ None => match db.try_find(&count.id, buf).map_err(Error::Find)? {
Some((obj, _location)) => {
stats.decoded_and_recompressed_objects += 1;
output::Entry::from_data(count, &obj)
@@ -397,7 +403,7 @@ mod types {
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
- FindExisting(crate::find::Error),
+ Find(gix_object::find::Error),
#[error(transparent)]
NewEntry(#[from] entry::Error),
}
diff --git a/vendor/gix-pack/src/find.rs b/vendor/gix-pack/src/find.rs
index b049d4d78..efc9513ed 100644
--- a/vendor/gix-pack/src/find.rs
+++ b/vendor/gix-pack/src/find.rs
@@ -1,57 +1,3 @@
-/// The error returned by methods of the [Find](crate::Find) trait.
-pub type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
-
-///
-pub mod existing {
- use gix_hash::ObjectId;
-
- /// The error returned by the [`find(…)`](crate::FindExt::find()) trait methods.
- #[derive(Debug, thiserror::Error)]
- #[allow(missing_docs)]
- pub enum Error {
- #[error(transparent)]
- Find(crate::find::Error),
- #[error("An object with id {} could not be found", .oid)]
- NotFound { oid: ObjectId },
- }
-}
-
-///
-pub mod existing_object {
- use gix_hash::ObjectId;
-
- /// The error returned by the various [`find_*`](crate::FindExt::find_commit()) trait methods.
- #[derive(Debug, thiserror::Error)]
- #[allow(missing_docs)]
- pub enum Error {
- #[error(transparent)]
- Find(crate::find::Error),
- #[error(transparent)]
- Decode(gix_object::decode::Error),
- #[error("An object with id {} could not be found", .oid)]
- NotFound { oid: ObjectId },
- #[error("Expected object of kind {} something else", .expected)]
- ObjectKind { expected: gix_object::Kind },
- }
-}
-
-///
-pub mod existing_iter {
- use gix_hash::ObjectId;
-
- /// The error returned by the various [`find_*`](crate::FindExt::find_commit()) trait methods.
- #[derive(Debug, thiserror::Error)]
- #[allow(missing_docs)]
- pub enum Error {
- #[error(transparent)]
- Find(crate::find::Error),
- #[error("An object with id {} could not be found", .oid)]
- NotFound { oid: ObjectId },
- #[error("Expected object of kind {} something else", .expected)]
- ObjectKind { expected: gix_object::Kind },
- }
-}
-
/// An Entry in a pack providing access to its data.
///
/// Its commonly retrieved by reading from a pack index file followed by a read from a pack data file.
diff --git a/vendor/gix-pack/src/find_traits.rs b/vendor/gix-pack/src/find_traits.rs
index 7c4821d81..787ed5b63 100644
--- a/vendor/gix-pack/src/find_traits.rs
+++ b/vendor/gix-pack/src/find_traits.rs
@@ -25,7 +25,7 @@ pub trait Find {
&self,
id: &gix_hash::oid,
buffer: &'a mut Vec<u8>,
- ) -> Result<Option<(gix_object::Data<'a>, Option<data::entry::Location>)>, find::Error> {
+ ) -> Result<Option<(gix_object::Data<'a>, Option<data::entry::Location>)>, gix_object::find::Error> {
self.try_find_cached(id, buffer, &mut crate::cache::Never)
}
@@ -40,7 +40,7 @@ pub trait Find {
id: &gix_hash::oid,
buffer: &'a mut Vec<u8>,
pack_cache: &mut dyn crate::cache::DecodeEntry,
- ) -> Result<Option<(gix_object::Data<'a>, Option<data::entry::Location>)>, find::Error>;
+ ) -> Result<Option<(gix_object::Data<'a>, Option<data::entry::Location>)>, gix_object::find::Error>;
/// Find the packs location where an object with `id` can be found in the database, or `None` if there is no pack
/// holding the object.
@@ -66,8 +66,6 @@ pub trait Find {
mod ext {
use gix_object::{BlobRef, CommitRef, CommitRefIter, Kind, ObjectRef, TagRef, TagRefIter, TreeRef, TreeRefIter};
- use crate::find;
-
macro_rules! make_obj_lookup {
($method:ident, $object_variant:path, $object_kind:path, $object_type:ty) => {
/// Like [`find(…)`][Self::find()], but flattens the `Result<Option<_>>` into a single `Result` making a non-existing object an error
@@ -76,21 +74,27 @@ mod ext {
&self,
id: &gix_hash::oid,
buffer: &'a mut Vec<u8>,
- ) -> Result<($object_type, Option<crate::data::entry::Location>), find::existing_object::Error> {
+ ) -> Result<($object_type, Option<crate::data::entry::Location>), gix_object::find::existing_object::Error>
+ {
let id = id.as_ref();
self.try_find(id, buffer)
- .map_err(find::existing_object::Error::Find)?
- .ok_or_else(|| find::existing_object::Error::NotFound {
+ .map_err(gix_object::find::existing_object::Error::Find)?
+ .ok_or_else(|| gix_object::find::existing_object::Error::NotFound {
oid: id.as_ref().to_owned(),
})
.and_then(|(o, l)| {
o.decode()
- .map_err(find::existing_object::Error::Decode)
+ .map_err(|err| gix_object::find::existing_object::Error::Decode {
+ source: err,
+ oid: id.to_owned(),
+ })
.map(|o| (o, l))
})
.and_then(|(o, l)| match o {
$object_variant(o) => return Ok((o, l)),
- _other => Err(find::existing_object::Error::ObjectKind {
+ o => Err(gix_object::find::existing_object::Error::ObjectKind {
+ oid: id.to_owned(),
+ actual: o.kind(),
expected: $object_kind,
}),
})
@@ -106,16 +110,18 @@ mod ext {
&self,
id: &gix_hash::oid,
buffer: &'a mut Vec<u8>,
- ) -> Result<($object_type, Option<crate::data::entry::Location>), find::existing_iter::Error> {
+ ) -> Result<($object_type, Option<crate::data::entry::Location>), gix_object::find::existing_iter::Error> {
let id = id.as_ref();
self.try_find(id, buffer)
- .map_err(find::existing_iter::Error::Find)?
- .ok_or_else(|| find::existing_iter::Error::NotFound {
+ .map_err(gix_object::find::existing_iter::Error::Find)?
+ .ok_or_else(|| gix_object::find::existing_iter::Error::NotFound {
oid: id.as_ref().to_owned(),
})
.and_then(|(o, l)| {
o.$into_iter()
- .ok_or_else(|| find::existing_iter::Error::ObjectKind {
+ .ok_or_else(|| gix_object::find::existing_iter::Error::ObjectKind {
+ oid: id.to_owned(),
+ actual: o.kind,
expected: $object_kind,
})
.map(|i| (i, l))
@@ -131,10 +137,11 @@ mod ext {
&self,
id: &gix_hash::oid,
buffer: &'a mut Vec<u8>,
- ) -> Result<(gix_object::Data<'a>, Option<crate::data::entry::Location>), find::existing::Error> {
+ ) -> Result<(gix_object::Data<'a>, Option<crate::data::entry::Location>), gix_object::find::existing::Error>
+ {
self.try_find(id, buffer)
- .map_err(find::existing::Error::Find)?
- .ok_or_else(|| find::existing::Error::NotFound {
+ .map_err(gix_object::find::existing::Error::Find)?
+ .ok_or_else(|| gix_object::find::existing::Error::NotFound {
oid: id.as_ref().to_owned(),
})
}
@@ -172,7 +179,7 @@ mod find_impls {
id: &oid,
buffer: &'a mut Vec<u8>,
pack_cache: &mut dyn crate::cache::DecodeEntry,
- ) -> Result<Option<(gix_object::Data<'a>, Option<data::entry::Location>)>, crate::find::Error> {
+ ) -> Result<Option<(gix_object::Data<'a>, Option<data::entry::Location>)>, gix_object::find::Error> {
(*self).try_find_cached(id, buffer, pack_cache)
}
@@ -202,7 +209,7 @@ mod find_impls {
id: &oid,
buffer: &'a mut Vec<u8>,
pack_cache: &mut dyn crate::cache::DecodeEntry,
- ) -> Result<Option<(gix_object::Data<'a>, Option<data::entry::Location>)>, find::Error> {
+ ) -> Result<Option<(gix_object::Data<'a>, Option<data::entry::Location>)>, gix_object::find::Error> {
self.deref().try_find_cached(id, buffer, pack_cache)
}
@@ -232,7 +239,7 @@ mod find_impls {
id: &oid,
buffer: &'a mut Vec<u8>,
pack_cache: &mut dyn crate::cache::DecodeEntry,
- ) -> Result<Option<(gix_object::Data<'a>, Option<data::entry::Location>)>, find::Error> {
+ ) -> Result<Option<(gix_object::Data<'a>, Option<data::entry::Location>)>, gix_object::find::Error> {
self.deref().try_find_cached(id, buffer, pack_cache)
}
@@ -262,7 +269,7 @@ mod find_impls {
id: &oid,
buffer: &'a mut Vec<u8>,
pack_cache: &mut dyn crate::cache::DecodeEntry,
- ) -> Result<Option<(gix_object::Data<'a>, Option<data::entry::Location>)>, find::Error> {
+ ) -> Result<Option<(gix_object::Data<'a>, Option<data::entry::Location>)>, gix_object::find::Error> {
self.deref().try_find_cached(id, buffer, pack_cache)
}
diff --git a/vendor/gix-pack/src/index/encode.rs b/vendor/gix-pack/src/index/encode.rs
index d9dad68ce..61c6f6de7 100644
--- a/vendor/gix-pack/src/index/encode.rs
+++ b/vendor/gix-pack/src/index/encode.rs
@@ -34,14 +34,14 @@ pub(crate) fn fanout(iter: &mut dyn ExactSizeIterator<Item = u8>) -> [u32; 256]
#[cfg(feature = "streaming-input")]
mod function {
+ use std::io;
+
use gix_features::{
hash,
progress::{self, DynNestedProgress},
};
- use std::io;
use super::{fanout, HIGH_BIT, LARGE_OFFSET_THRESHOLD};
-
use crate::index::V2_SIGNATURE;
struct Count<W> {
diff --git a/vendor/gix-pack/src/index/traverse/with_index.rs b/vendor/gix-pack/src/index/traverse/with_index.rs
index 91382034c..88b3dea96 100644
--- a/vendor/gix-pack/src/index/traverse/with_index.rs
+++ b/vendor/gix-pack/src/index/traverse/with_index.rs
@@ -1,7 +1,6 @@
use std::sync::atomic::{AtomicBool, Ordering};
-use gix_features::parallel;
-use gix_features::progress::DynNestedProgress;
+use gix_features::{parallel, progress::DynNestedProgress};
use super::Error;
use crate::{
diff --git a/vendor/gix-pack/src/index/traverse/with_lookup.rs b/vendor/gix-pack/src/index/traverse/with_lookup.rs
index 3759dae5e..9f1db3d05 100644
--- a/vendor/gix-pack/src/index/traverse/with_lookup.rs
+++ b/vendor/gix-pack/src/index/traverse/with_lookup.rs
@@ -1,9 +1,8 @@
use std::sync::atomic::{AtomicBool, Ordering};
-use gix_features::progress::{Count, DynNestedProgress};
use gix_features::{
parallel::{self, in_parallel_if},
- progress::{self, Progress},
+ progress::{self, Count, DynNestedProgress, Progress},
threading::{lock, Mutable, OwnShared},
zlib,
};
diff --git a/vendor/gix-pack/src/index/verify.rs b/vendor/gix-pack/src/index/verify.rs
index d259a6a38..343a647b4 100644
--- a/vendor/gix-pack/src/index/verify.rs
+++ b/vendor/gix-pack/src/index/verify.rs
@@ -1,7 +1,7 @@
use std::sync::atomic::AtomicBool;
use gix_features::progress::{DynNestedProgress, Progress};
-use gix_object::{bstr::ByteSlice, WriteTo};
+use gix_object::WriteTo;
use crate::index;
@@ -235,7 +235,7 @@ impl index::File {
object_kind: gix_object::Kind,
buf: &[u8],
index_entry: &index::Entry,
- progress: &dyn gix_features::progress::Progress,
+ _progress: &dyn gix_features::progress::Progress,
) -> Result<(), integrity::Error> {
if let Mode::HashCrc32Decode | Mode::HashCrc32DecodeEncode = verify_mode {
use gix_object::Kind::*;
@@ -252,21 +252,12 @@ impl index::File {
encode_buf.clear();
object.write_to(&mut *encode_buf)?;
if encode_buf.as_slice() != buf {
- let mut should_return_error = true;
- if let Tree = object_kind {
- if buf.as_bstr().find(b"100664").is_some() || buf.as_bstr().find(b"100640").is_some() {
- progress.info(format!("Tree object {} would be cleaned up during re-serialization, replacing mode '100664|100640' with '100644'", index_entry.oid));
- should_return_error = false
- }
- }
- if should_return_error {
- return Err(integrity::Error::ObjectEncodeMismatch {
- kind: object_kind,
- id: index_entry.oid,
- expected: buf.into(),
- actual: encode_buf.clone().into(),
- });
- }
+ return Err(integrity::Error::ObjectEncodeMismatch {
+ kind: object_kind,
+ id: index_entry.oid,
+ expected: buf.into(),
+ actual: encode_buf.clone().into(),
+ });
}
}
}
diff --git a/vendor/gix-pack/src/index/write/mod.rs b/vendor/gix-pack/src/index/write/mod.rs
index d1402fa86..3ecb7347b 100644
--- a/vendor/gix-pack/src/index/write/mod.rs
+++ b/vendor/gix-pack/src/index/write/mod.rs
@@ -1,8 +1,7 @@
use std::{convert::TryInto, io, sync::atomic::AtomicBool};
pub use error::Error;
-use gix_features::progress::prodash::DynNestedProgress;
-use gix_features::progress::{self, Count, Progress};
+use gix_features::progress::{self, prodash::DynNestedProgress, Count, Progress};
use crate::cache::delta::{traverse, Tree};
diff --git a/vendor/gix-pack/src/lib.rs b/vendor/gix-pack/src/lib.rs
index 200b87019..b56d1fe98 100755
--- a/vendor/gix-pack/src/lib.rs
+++ b/vendor/gix-pack/src/lib.rs
@@ -12,10 +12,10 @@
//! in order to decompress packs in parallel and without any waste.
//! ## Feature Flags
#![cfg_attr(
- feature = "document-features",
- cfg_attr(doc, doc = ::document_features::document_features!())
+ all(doc, feature = "document-features"),
+ doc = ::document_features::document_features!()
)]
-#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
+#![cfg_attr(all(doc, feature = "document-features"), feature(doc_cfg, doc_auto_cfg))]
#![deny(missing_docs, rust_2018_idioms, unsafe_code)]
///