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();
}
}
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(())
}
}