Skip to content

Commit

Permalink
first very basic progress implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Jun 30, 2020
1 parent da3ae1c commit b820717
Show file tree
Hide file tree
Showing 10 changed files with 161 additions and 33 deletions.
33 changes: 32 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pretty-cli = ["structopt",
"prodash/log-renderer",
"prodash/tui-renderer",
"prodash/localtime"]
lean-cli = ["argh", "git-features/progress-log"]
lean-cli = ["argh", "git-features/progress-log", "env_logger"]

[dependencies]
anyhow = "1.0.31"
Expand All @@ -38,6 +38,7 @@ git-features = { version = "0.1.0", path = "git-features" }
structopt = { version = "0.3.14", optional = true }
argh = { version = "0.1.3", optional = true }
prodash = { version = "4.0.4", optional = true, default-features = false }
env_logger = { version = "0.7.1", optional = true, default-features = false, features = ["humantime", "termcolor", "atty"] }

[profile.release]
overflow-checks = false
Expand Down
12 changes: 6 additions & 6 deletions git-features/src/progress/log.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::progress::{MessageLevel, Progress};
use std::time::Duration;

pub struct LogProgress {
pub struct Log {
name: String,
max: Option<u32>,
unit: Option<&'static str>,
Expand All @@ -10,9 +10,9 @@ pub struct LogProgress {

const EMIT_LOG_EVERY_S: f32 = 0.5;

impl LogProgress {
impl Log {
pub fn new(name: impl Into<String>) -> Self {
LogProgress {
Log {
name: name.into(),
max: None,
unit: None,
Expand All @@ -21,11 +21,11 @@ impl LogProgress {
}
}

impl Progress for LogProgress {
type SubProgress = LogProgress;
impl Progress for Log {
type SubProgress = Log;

fn add_child(&mut self, name: impl Into<String>) -> Self::SubProgress {
LogProgress::new(format!("{}::{}", self.name, Into::<String>::into(name)))
Log::new(format!("{}::{}", self.name, Into::<String>::into(name)))
}

fn init(&mut self, max: Option<u32>, unit: Option<&'static str>) {
Expand Down
59 changes: 54 additions & 5 deletions git-features/src/progress/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,18 @@ pub trait Progress {
mod log;

#[cfg(feature = "progress-log")]
pub use self::log::LogProgress;
pub use self::log::Log;

#[cfg(feature = "progress-prodash")]
mod prodash;

pub struct DiscardProgress;
pub struct Discard;

impl Progress for DiscardProgress {
type SubProgress = DiscardProgress;
impl Progress for Discard {
type SubProgress = Discard;

fn add_child(&mut self, _name: impl Into<String>) -> Self::SubProgress {
DiscardProgress
Discard
}

fn init(&mut self, _max: Option<u32>, _unit: Option<&'static str>) {}
Expand All @@ -82,3 +82,52 @@ impl Progress for DiscardProgress {

fn message(&mut self, _level: MessageLevel, _message: impl Into<String>) {}
}

pub enum DoOrDiscard<T> {
Do(T),
Discard,
}

impl<T> From<Option<T>> for DoOrDiscard<T>
where
T: Progress,
{
fn from(p: Option<T>) -> Self {
match p {
Some(p) => DoOrDiscard::Do(p),
None => DoOrDiscard::Discard,
}
}
}

impl<T> Progress for DoOrDiscard<T>
where
T: Progress,
{
type SubProgress = DoOrDiscard<T::SubProgress>;

fn add_child(&mut self, name: impl Into<String>) -> Self::SubProgress {
match self {
DoOrDiscard::Discard => DoOrDiscard::Discard,
DoOrDiscard::Do(p) => DoOrDiscard::Do(p.add_child(name)),
}
}

fn init(&mut self, max: Option<u32>, unit: Option<&'static str>) {
if let DoOrDiscard::Do(p) = self {
p.init(max, unit)
}
}

fn set(&mut self, step: u32) {
if let DoOrDiscard::Do(p) = self {
p.set(step)
}
}

fn message(&mut self, level: MessageLevel, message: impl Into<String>) {
if let DoOrDiscard::Do(p) = self {
p.message(level, message)
}
}
}
3 changes: 3 additions & 0 deletions git-odb/src/pack/file/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ impl File {
pub fn num_objects(&self) -> u32 {
self.num_objects
}
pub fn path(&self) -> &Path {
&self.path
}
pub fn checksum(&self) -> object::Id {
object::Id::from_20_bytes(&self.data[self.data.len() - SHA1_SIZE..])
}
Expand Down
51 changes: 43 additions & 8 deletions git-odb/src/pack/index/verify.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{pack, pack::index};
use git_features::progress::{self, Progress};
use git_object::SHA1_SIZE;
use quick_error::quick_error;

Expand Down Expand Up @@ -43,18 +44,27 @@ impl index::File {
/// If `pack` is provided, it is expected (and validated to be) the pack belonging to this index.
/// It will be used to validate internal integrity of the pack before checking each objects integrity
/// is indeed as advertised via its SHA1 as stored in this index, as well as the CRC32 hash.
pub fn verify_checksum_of_index(
pub fn verify_checksum_of_index<P>(
&self,
pack: Option<&pack::File>,
_progress: Option<impl git_features::progress::Progress>,
) -> Result<git_object::Id, ChecksumError> {
progress: Option<P>,
) -> Result<git_object::Id, ChecksumError>
where
P: Progress,
<P as Progress>::SubProgress: Send,
{
use crate::pack::{cache, ResolvedBase};
use git_features::parallel::{self, in_parallel_if};

let verify_self = || {
let mut root = progress::DoOrDiscard::from(progress);
let mut progress = root.add_child("Sha1 of index");

let mut verify_self = || {
progress.info("begin");
let mut hasher = git_features::hash::Sha1::default();
hasher.update(&self.data[..self.data.len() - SHA1_SIZE]);
let actual = hasher.digest();
progress.done("finished");

let expected = self.checksum_of_index();
if actual == expected {
Expand All @@ -72,7 +82,17 @@ impl index::File {
expected: self.checksum_of_pack(),
});
}
let (pack_res, id) = parallel::join(|| pack.verify_checksum(), verify_self);
let mut progress =
root.add_child(format!("Sha1 of pack at '{}'", pack.path().display()));
let (pack_res, id) = parallel::join(
|| {
progress.info("begin");
let res = pack.verify_checksum();
progress.done("finished");
res
},
verify_self,
);
pack_res?;
let id = id?;

Expand All @@ -82,19 +102,28 @@ impl index::File {
v
};

struct Reducer;
struct Reducer<P> {
progress: P,
seen: u32,
}

impl parallel::Reducer for Reducer {
impl<P> parallel::Reducer for Reducer<P>
where
P: Progress,
{
type Input = Result<(), ChecksumError>;
type Output = ();
type Error = ChecksumError;

fn feed(&mut self, input: Self::Input) -> Result<(), Self::Error> {
self.seen += 1;
self.progress.set(self.seen);
input?;
Ok(())
}

fn finalize(&mut self) -> Result<Self::Output, Self::Error> {
self.progress.done("finished");
Ok(())
}
}
Expand All @@ -106,6 +135,9 @@ impl index::File {
.into_iter();
let state_per_thread =
|| (cache::DecodeEntryLRU::default(), Vec::with_capacity(2048));
let mut reduce_progress = root.add_child("reduce");
reduce_progress.init(Some(self.num_objects()), Some("objects"));

in_parallel_if(
there_are_enough_entries_to_process,
input_chunks,
Expand Down Expand Up @@ -172,7 +204,10 @@ impl index::File {
}
Ok(())
},
Reducer,
Reducer {
progress: reduce_progress,
seen: 0,
},
)?;

Ok(id)
Expand Down
7 changes: 3 additions & 4 deletions git-odb/tests/pack/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ mod method {
}
}

use git_features::progress::DiscardProgress;
use git_features::progress::Discard;
#[test]
fn pack_lookup() {
for (index_path, pack_path) in &[
Expand All @@ -115,7 +115,7 @@ fn pack_lookup() {
assert_eq!(pack.kind(), pack::Kind::V2);
assert_eq!(pack.num_objects(), idx.num_objects());
assert_eq!(
idx.verify_checksum_of_index(Some(&pack), DiscardProgress.into())
idx.verify_checksum_of_index(Some(&pack), Discard.into())
.unwrap(),
idx.checksum_of_index()
);
Expand Down Expand Up @@ -159,8 +159,7 @@ fn iter() {
assert_eq!(idx.version(), *version);
assert_eq!(idx.num_objects(), *num_objects);
assert_eq!(
idx.verify_checksum_of_index(None, DiscardProgress.into())
.unwrap(),
idx.verify_checksum_of_index(None, Discard.into()).unwrap(),
idx.checksum_of_index()
);
assert_eq!(idx.checksum_of_index(), hex_to_id(index_checksum));
Expand Down
11 changes: 8 additions & 3 deletions gitoxide-core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
use anyhow::{anyhow, Context, Result};
use git_features::progress::Progress;
use std::{io, path::Path};

pub fn init() -> Result<()> {
git_repository::init::repository().with_context(|| "Repository initialization failed")
}

pub fn verify_pack_or_pack_index(
pub fn verify_pack_or_pack_index<P>(
path: impl AsRef<Path>,
progress: Option<impl git_features::progress::Progress>,
progress: Option<P>,
mut out: impl io::Write,
mut err: impl io::Write,
) -> Result<()> {
) -> Result<()>
where
P: Progress,
<P as Progress>::SubProgress: Send,
{
let path = path.as_ref();
let ext = path.extension()
.and_then(|ext| ext.to_str())
Expand Down
11 changes: 8 additions & 3 deletions src/plumbing/lean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,20 @@ mod options {
}

use anyhow::Result;
use git_features::progress;
use gitoxide_core as core;
use std::io::{stderr, stdout};

pub fn main() -> Result<()> {
pub use options::*;
let cli: Args = argh::from_env();
env_logger::init();
match cli.subcommand {
SubCommands::VerifyPack(VerifyPack { path }) => {
core::verify_pack_or_pack_index(path, stdout(), stderr())
}
SubCommands::VerifyPack(VerifyPack { path }) => core::verify_pack_or_pack_index(
path,
progress::Log::new("verify").into(),
stdout(),
stderr(),
),
}
}

0 comments on commit b820717

Please sign in to comment.