use std::{path::Path, sync::atomic::AtomicBool}; use gix::progress::DynNestedProgress; use crate::{ corpus, corpus::{Run, Task}, pack::verify::Algorithm,}; impl Task { pub fn perform( &self, run: &mut Run, repo: &Path, progress: &mut corpus::engine::ProgressItem, threads: Option<usize>, should_interrupt: &AtomicBool, ) { let start = std::time::Instant::now(); if let Err(err) = self.execute.execute(repo, progress, threads, should_interrupt) { run.error = Some(format!("{err:#?}")); } run.duration = start.elapsed(); }} /// Note that once runs have been recorded, the implementation must not change anymore to keep it comparable./// If changes have be done, rather change the name of the owning task to start a new kind of task.pub(crate) trait Execute { fn execute( &self, repo: &Path, progress: &mut corpus::engine::ProgressItem, threads: Option<usize>, should_interrupt: &AtomicBool, ) -> anyhow::Result<()>;} pub(crate) static ALL: &[Task] = &[ #[cfg(feature = "archive")] Task { short_name: "SWTR", description: "stream worktree", execute_exclusive: false, execute: &WorktreeStream, }, Task { short_name: "OPNR", description: "open repository (isolated)", execute_exclusive: false, execute: &OpenRepo, }, Task { short_name: "POCN", description: "packed object count", execute_exclusive: false, execute: &CountPackedObjects, }, Task { short_name: "VERI", description: "verify object database", execute_exclusive: true, execute: &VerifyOdb, },]; #[cfg(feature = "archive")]struct WorktreeStream; #[cfg(feature = "archive")]impl Execute for WorktreeStream { fn execute( &self, repo: &Path, progress: &mut corpus::engine::ProgressItem, _threads: Option<usize>, should_interrupt: &AtomicBool, ) -> anyhow::Result<()> { use gix::Progress; let repo = gix::open_opts(repo, gix::open::Options::isolated())?; let (stream, _) = { let _span = gix::trace::coarse!("read index and create worktree stream"); repo.worktree_stream(repo.head_commit()?.tree_id()?)? }; progress.init(None, gix::progress::bytes()); std::io::copy( &mut stream.into_read(), &mut gix::features::interrupt::Write { inner: gix::features::progress::Write { inner: std::io::sink(), progress, }, should_interrupt, }, )?; Ok(()) }} struct OpenRepo; impl Execute for OpenRepo { fn execute( &self, repo: &Path, _progress: &mut corpus::engine::ProgressItem, _threads: Option<usize>, _should_interrupt: &AtomicBool, ) -> anyhow::Result<()> { gix::open_opts(repo, gix::open::Options::isolated())?; Ok(()) }} struct CountPackedObjects; impl Execute for CountPackedObjects { fn execute( &self, repo: &Path, _progress: &mut corpus::engine::ProgressItem, _threads: Option<usize>, _should_interrupt: &AtomicBool, ) -> anyhow::Result<()> { let repo = gix::open_opts(repo, gix::open::Options::isolated())?; repo.objects.packed_object_count()?; Ok(()) }} struct VerifyOdb; impl Execute for VerifyOdb { fn execute( &self, repo: &Path, progress: &mut corpus::engine::ProgressItem, threads: Option<usize>, should_interrupt: &AtomicBool, ) -> anyhow::Result<()> { let repo = gix::open_opts(repo, gix::open::Options::isolated())?; crate::repository::verify::integrity( repo, std::io::sink(), progress.add_child("integrity".into()), should_interrupt, crate::repository::verify::Context { output_statistics: None, thread_limit: threads, verify_mode: Default::default(), algorithm: Algorithm::LessTime, }, )?; Ok(()) }}
use std::{path::Path, sync::atomic::AtomicBool};
use gix::progress::DynNestedProgress;
use crate::{
corpus,
corpus::{Run, Task},
pack::verify::Algorithm,
};
impl Task {
pub fn perform(
&self,
run: &mut Run,
repo: &Path,
progress: &mut corpus::engine::ProgressItem,
threads: Option<usize>,
should_interrupt: &AtomicBool,
) {
let start = std::time::Instant::now();
if let Err(err) = self.execute.execute(repo, progress, threads, should_interrupt) {
run.error = Some(format!("{err:#?}"));
}
run.duration = start.elapsed();
}
}
/// Note that once runs have been recorded, the implementation must not change anymore to keep it comparable.
/// If changes have be done, rather change the name of the owning task to start a new kind of task.
pub(crate) trait Execute {
fn execute(
&self,
repo: &Path,
progress: &mut corpus::engine::ProgressItem,
threads: Option<usize>,
should_interrupt: &AtomicBool,
) -> anyhow::Result<()>;
}
pub(crate) static ALL: &[Task] = &[
#[cfg(feature = "archive")]
Task {
short_name: "SWTR",
description: "stream worktree",
execute_exclusive: false,
execute: &WorktreeStream,
},
Task {
short_name: "OPNR",
description: "open repository (isolated)",
execute_exclusive: false,
execute: &OpenRepo,
},
Task {
short_name: "POCN",
description: "packed object count",
execute_exclusive: false,
execute: &CountPackedObjects,
},
Task {
short_name: "VERI",
description: "verify object database",
execute_exclusive: true,
execute: &VerifyOdb,
},
];
#[cfg(feature = "archive")]
struct WorktreeStream;
#[cfg(feature = "archive")]
impl Execute for WorktreeStream {
fn execute(
&self,
repo: &Path,
progress: &mut corpus::engine::ProgressItem,
_threads: Option<usize>,
should_interrupt: &AtomicBool,
) -> anyhow::Result<()> {
use gix::Progress;
let repo = gix::open_opts(repo, gix::open::Options::isolated())?;
let (stream, _) = {
let _span = gix::trace::coarse!("read index and create worktree stream");
repo.worktree_stream(repo.head_commit()?.tree_id()?)?
};
progress.init(None, gix::progress::bytes());
std::io::copy(
&mut stream.into_read(),
&mut gix::features::interrupt::Write {
inner: gix::features::progress::Write {
inner: std::io::sink(),
progress,
},
should_interrupt,
},
)?;
Ok(())
}
}
struct OpenRepo;
impl Execute for OpenRepo {
fn execute(
&self,
repo: &Path,
_progress: &mut corpus::engine::ProgressItem,
_threads: Option<usize>,
_should_interrupt: &AtomicBool,
) -> anyhow::Result<()> {
gix::open_opts(repo, gix::open::Options::isolated())?;
Ok(())
}
}
struct CountPackedObjects;
impl Execute for CountPackedObjects {
fn execute(
&self,
repo: &Path,
_progress: &mut corpus::engine::ProgressItem,
_threads: Option<usize>,
_should_interrupt: &AtomicBool,
) -> anyhow::Result<()> {
let repo = gix::open_opts(repo, gix::open::Options::isolated())?;
repo.objects.packed_object_count()?;
Ok(())
}
}
struct VerifyOdb;
impl Execute for VerifyOdb {
fn execute(
&self,
repo: &Path,
progress: &mut corpus::engine::ProgressItem,
threads: Option<usize>,
should_interrupt: &AtomicBool,
) -> anyhow::Result<()> {
let repo = gix::open_opts(repo, gix::open::Options::isolated())?;
crate::repository::verify::integrity(
repo,
std::io::sink(),
progress.add_child("integrity".into()),
should_interrupt,
crate::repository::verify::Context {
output_statistics: None,
thread_limit: threads,
verify_mode: Default::default(),
algorithm: Algorithm::LessTime,
},
)?;
Ok(())
}
}