Skip to content

Commit

Permalink
adapt to changes related to usage of gix-object::Find trait where n…
Browse files Browse the repository at this point in the history
…ecessary
  • Loading branch information
Byron committed Nov 5, 2023
1 parent dbb6886 commit 5761a4d
Show file tree
Hide file tree
Showing 38 changed files with 192 additions and 223 deletions.
2 changes: 1 addition & 1 deletion gitoxide-core/src/hours/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ where
let mut skipped_merge_commits = 0;
const CHUNK_SIZE: usize = 50;
let mut chunk = Vec::with_capacity(CHUNK_SIZE);
let mut commit_iter = commit_id.ancestors(|oid, buf| repo.objects.find_commit_iter(oid, buf));
let mut commit_iter = commit_id.ancestors(&repo.objects);
let mut is_shallow = false;
while let Some(c) = commit_iter.next() {
progress.inc();
Expand Down
63 changes: 44 additions & 19 deletions gitoxide-core/src/index/checkout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use std::{
};

use anyhow::bail;
use gix::{prelude::FindExt, worktree::state::checkout, NestedProgress, Progress};
use gix::objs::find::Error;
use gix::{worktree::state::checkout, NestedProgress, Progress};

use crate::{
index,
Expand Down Expand Up @@ -89,20 +90,9 @@ pub fn checkout_exclusive(
Some(repo) => gix::worktree::state::checkout(
&mut index,
dest_directory,
{
let objects = repo.objects.into_arc()?;
move |oid, buf| {
objects.find_blob(oid, buf).ok();
if empty_files {
// We always want to query the ODB here…
objects.find_blob(oid, buf)?;
buf.clear();
// …but write nothing
Ok(gix::objs::BlobRef { data: buf })
} else {
objects.find_blob(oid, buf)
}
}
EmptyOrDb {
empty_files,
db: repo.objects.into_arc()?,
},
&files,
&bytes,
Expand All @@ -112,10 +102,7 @@ pub fn checkout_exclusive(
None => gix::worktree::state::checkout(
&mut index,
dest_directory,
|_, buf| {
buf.clear();
Ok(gix::objs::BlobRef { data: buf })
},
Empty,
&files,
&bytes,
should_interrupt,
Expand Down Expand Up @@ -184,3 +171,41 @@ pub fn checkout_exclusive(
}
Ok(())
}

#[derive(Clone)]
struct EmptyOrDb<Find> {
empty_files: bool,
db: Find,
}

impl<Find> gix::objs::Find for EmptyOrDb<Find>
where
Find: gix::objs::Find,
{
fn try_find<'a>(&self, id: &gix::oid, buf: &'a mut Vec<u8>) -> Result<Option<gix::objs::Data<'a>>, Error> {
if self.empty_files {
// We always want to query the ODB here…
let Some(kind) = self.db.try_find(id, buf)?.map(|d| d.kind) else {
return Ok(None);
};
buf.clear();
// …but write nothing
Ok(Some(gix::objs::Data { kind, data: buf }))
} else {
self.db.try_find(id, buf)
}
}
}

#[derive(Clone)]
struct Empty;

impl gix::objs::Find for Empty {
fn try_find<'a>(&self, _id: &gix::oid, buffer: &'a mut Vec<u8>) -> Result<Option<gix::objs::Data<'a>>, Error> {
buffer.clear();
Ok(Some(gix::objs::Data {
kind: gix::object::Kind::Blob,
data: buffer,
}))
}
}
2 changes: 1 addition & 1 deletion gitoxide-core/src/index/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub fn verify(
let file = parse_file(index_path, object_hash)?;
file.verify_integrity()?;
file.verify_entries()?;
file.verify_extensions(false, gix::index::verify::extensions::no_find)?;
file.verify_extensions(false, gix::objs::find::Never)?;
#[cfg_attr(not(feature = "serde"), allow(irrefutable_let_patterns))]
if let crate::OutputFormat::Human = format {
writeln!(out, "OK").ok();
Expand Down
17 changes: 4 additions & 13 deletions gitoxide-core/src/pack/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,7 @@ use std::{ffi::OsStr, io, path::Path, str::FromStr, time::Instant};

use anyhow::anyhow;
use gix::{
hash,
hash::ObjectId,
interrupt,
objs::bstr::ByteVec,
odb::{pack, pack::FindExt},
parallel::InOrderIter,
prelude::Finalize,
hash, hash::ObjectId, interrupt, objs::bstr::ByteVec, odb::pack, parallel::InOrderIter, prelude::Finalize,
progress, traverse, Count, NestedProgress, Progress,
};

Expand Down Expand Up @@ -136,12 +130,9 @@ where
.collect::<Result<Vec<_>, _>>()?;
let handle = repo.objects.into_shared_arc().to_cache_arc();
let iter = Box::new(
traverse::commit::Ancestors::new(tips, traverse::commit::ancestors::State::default(), {
let handle = handle.clone();
move |oid, buf| handle.find_commit_iter(oid, buf).map(|t| t.0)
})
.map(|res| res.map_err(|err| Box::new(err) as Box<_>).map(|c| c.id))
.inspect(move |_| progress.inc()),
traverse::commit::Ancestors::new(tips, traverse::commit::ancestors::State::default(), handle.clone())
.map(|res| res.map_err(|err| Box::new(err) as Box<_>).map(|c| c.id))
.inspect(move |_| progress.inc()),
);
(handle, iter)
}
Expand Down
4 changes: 2 additions & 2 deletions gitoxide-core/src/pack/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ pub fn from_pack(
directory,
&mut progress,
ctx.should_interrupt,
None,
None::<gix::objs::find::Never>,
options,
)
}
Expand All @@ -105,7 +105,7 @@ pub fn from_pack(
directory,
&mut progress,
ctx.should_interrupt,
None,
None::<gix::objs::find::Never>,
options,
),
}
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/pack/receive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ fn receive_pack_blocking<W: io::Write>(
directory.take().as_deref(),
&mut progress,
&ctx.should_interrupt,
None,
None::<gix::objs::find::Never>,
options,
)
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
Expand Down
101 changes: 77 additions & 24 deletions gitoxide-core/src/query/engine/update.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
use std::cell::RefCell;
use std::{
convert::Infallible,
sync::atomic::{AtomicUsize, Ordering},
time::Instant,
};

use anyhow::{anyhow, bail};
use gix::objs::find::Error;
use gix::{
bstr::{BStr, BString, ByteSlice},
features::progress,
object::tree::diff::rewrites::CopySource,
parallel::{InOrderIter, SequenceId},
prelude::FindExt,
prelude::ObjectIdExt,
Count, Progress,
};
Expand Down Expand Up @@ -150,13 +151,18 @@ pub fn update(
});
r
};

#[derive(Clone)]
struct Task {
commit: gix::hash::ObjectId,
parent_commit: Option<gix::hash::ObjectId>,
compute_stats: bool,
}

type Packet = (SequenceId, Vec<Task>);

let (tx_tree_ids, stat_threads) = {
let (tx, rx) = crossbeam_channel::unbounded::<(SequenceId, Vec<Task>)>();
let (tx, rx) = crossbeam_channel::unbounded::<Packet>();
let stat_workers = (0..threads)
.map(|_| {
scope.spawn({
Expand Down Expand Up @@ -304,46 +310,94 @@ pub fn update(
};
drop(tx_stats);

const CHUNK_SIZE: usize = 50;
let mut chunk = Vec::with_capacity(CHUNK_SIZE);
let mut chunk_id: SequenceId = 0;
let commit_iter = gix::interrupt::Iter::new(
commit_id.ancestors(|oid, buf| -> Result<_, gix::object::find::existing::Error> {
let obj = repo.objects.find(oid, buf)?;
traverse_progress.inc();
if known_commits.binary_search(&oid.to_owned()).is_err() {
#[derive(Clone)]
struct Db<'a, Find: Clone> {
inner: &'a Find,
progress: &'a dyn gix::progress::Count,
chunk: std::cell::RefCell<Vec<Task>>,
chunk_id: std::cell::RefCell<SequenceId>,
chunk_size: usize,
tx: crossbeam_channel::Sender<Packet>,
known_commits: &'a [gix::ObjectId],
}

impl<'a, Find> Db<'a, Find>
where
Find: gix::prelude::Find + Clone,
{
fn new(
inner: &'a Find,
progress: &'a dyn gix::progress::Count,
chunk_size: usize,
tx: crossbeam_channel::Sender<Packet>,
known_commits: &'a [gix::ObjectId],
) -> Self {
Self {
inner,
progress,
known_commits,
tx,
chunk_size,
chunk_id: 0.into(),
chunk: RefCell::new(Vec::with_capacity(chunk_size)),
}
}

fn send_last_chunk(self) {
self.tx.send((self.chunk_id.into_inner(), self.chunk.into_inner())).ok();
}
}

impl<'a, Find> gix::prelude::Find for Db<'a, Find>
where
Find: gix::prelude::Find + Clone,
{
fn try_find<'b>(&self, id: &gix::oid, buf: &'b mut Vec<u8>) -> Result<Option<gix::objs::Data<'b>>, Error> {
let obj = self.inner.try_find(id, buf)?;
let Some(obj) = obj else { return Ok(None) };
if !obj.kind.is_commit() {
return Ok(None);
}

self.progress.inc();
if self.known_commits.binary_search(&id.to_owned()).is_err() {
let res = {
let mut parents = gix::objs::CommitRefIter::from_bytes(obj.data).parent_ids();
let res = parents.next().map(|first_parent| (Some(first_parent), oid.to_owned()));
let res = parents.next().map(|first_parent| (Some(first_parent), id.to_owned()));
match parents.next() {
Some(_) => None,
None => res,
}
};
if let Some((first_parent, commit)) = res {
chunk.push(Task {
self.chunk.borrow_mut().push(Task {
parent_commit: first_parent,
commit,
compute_stats: true,
});
} else {
chunk.push(Task {
self.chunk.borrow_mut().push(Task {
parent_commit: None,
commit: oid.to_owned(),
commit: id.to_owned(),
compute_stats: false,
});
}
if chunk.len() == CHUNK_SIZE {
tx_tree_ids
.send((chunk_id, std::mem::replace(&mut chunk, Vec::with_capacity(CHUNK_SIZE))))
if self.chunk.borrow().len() == self.chunk_size {
self.tx
.send((
*self.chunk_id.borrow(),
std::mem::replace(&mut self.chunk.borrow_mut(), Vec::with_capacity(self.chunk_size)),
))
.ok();
chunk_id += 1;
*self.chunk_id.borrow_mut() += 1;
}
}
Ok(gix::objs::CommitRefIter::from_bytes(obj.data))
}),
|| anyhow!("Cancelled by user"),
);
Ok(Some(obj))
}
}

let db = Db::new(&repo.objects, &traverse_progress, 50, tx_tree_ids, &known_commits);
let commit_iter = gix::interrupt::Iter::new(commit_id.ancestors(&db), || anyhow!("Cancelled by user"));
let mut commits = Vec::new();
for c in commit_iter {
match c?.map(|c| c.id) {
Expand All @@ -361,8 +415,7 @@ pub fn update(
Err(err) => return Err(err.into()),
};
}
tx_tree_ids.send((chunk_id, chunk)).ok();
drop(tx_tree_ids);
db.send_last_chunk();
let saw_new_commits = !commits.is_empty();
if saw_new_commits {
traverse_progress.show_throughput(start);
Expand Down
6 changes: 1 addition & 5 deletions gitoxide-core/src/repository/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::OutputFormat;
use anyhow::{bail, Context};
use gix::bstr::{BStr, BString};
use gix::index::Entry;
use gix::prelude::FindExt;
use gix::Progress;
use gix_status::index_as_worktree::traits::FastEq;
use gix_status::index_as_worktree::{Change, Conflict, EntryStatus};
Expand Down Expand Up @@ -80,10 +79,7 @@ pub fn show(
&mut printer,
FastEq,
Submodule,
{
let odb = repo.objects.clone().into_arc()?;
move |id, buf| odb.find_blob(id, buf)
},
repo.objects.clone().into_arc()?,
&mut progress,
pathspec.detach()?,
repo.filter_pipeline(Some(gix::hash::ObjectId::empty_tree(repo.object_hash())))?
Expand Down
6 changes: 1 addition & 5 deletions gitoxide-core/src/repository/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,7 @@ pub fn integrity(
if let Some(index) = repo.worktree().map(|wt| wt.index()).transpose()? {
index.verify_integrity()?;
index.verify_entries()?;
index.verify_extensions(true, {
use gix::prelude::FindExt;
let objects = repo.objects;
move |oid, buf: &mut Vec<u8>| objects.find_tree_iter(oid, buf).ok()
})?;
index.verify_extensions(true, repo.objects)?;
progress.info(format!("Index at '{}' OK", index.path().display()));
}
match output_statistics {
Expand Down
8 changes: 2 additions & 6 deletions gix-archive/tests/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ mod from_tree {
use gix_archive::Format;
use gix_attributes::glob::pattern::Case;
use gix_object::tree::EntryMode;
use gix_object::FindExt;
use gix_testtools::bstr::ByteSlice;
use gix_worktree::stack::state::attributes::Source;

Expand Down Expand Up @@ -230,14 +229,11 @@ mod from_tree {
let (dir, head_tree, odb, mut cache) = basic()?;
let mut stream = gix_worktree_stream::from_tree(
head_tree,
{
let odb = odb.clone();
move |id, buf| odb.find(id, buf)
},
odb.clone(),
noop_pipeline(),
move |rela_path, mode, attrs| {
cache
.at_entry(rela_path, mode.is_tree().into(), |id, buf| odb.find_blob(id, buf))
.at_entry(rela_path, mode.is_tree().into(), &odb)
.map(|entry| entry.matching_attributes(attrs))
.map(|_| ())
},
Expand Down
Loading

0 comments on commit 5761a4d

Please sign in to comment.