1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
//! This module contains the functionality for generating reports.
use rayon::prelude::*;
use std::collections::BTreeMap;
use std::path::Path;
use target::TargetCollector;
use thiserror::Error;
use crate::repository_view::{RepositoryView, RepositoryViewError, RepositoryViewResult};
mod target;
#[allow(missing_docs)]
#[derive(Error, Debug)]
pub enum CollectorError {
#[error(transparent)]
FromRepositoryView(#[from] RepositoryViewError),
#[error(transparent)]
FromStdIo(#[from] std::io::Error),
}
/// The result type used when multiple kinds of errors can be encountered during collection.
pub type CollectorResult<T> = Result<T, CollectorError>;
/// This type represents a [`BTreeMap`] using an optional [`String`] for keys, which represents the
/// parent directory for a group of reports ([`Vec<RepositoryView>`]). The values corresponding to those keys
/// are the actual groups of reports.
///
/// We use a [`BTreeMap`] instead of a [`HashMap`](std::collections::HashMap) in order to have
/// sorted keys.
pub type RepositoryCollection = BTreeMap<Option<String>, Vec<RepositoryView>>;
type UnprocessedRepositoryView = RepositoryViewResult<RepositoryView>;
/// A unit struct that provides [`Self::run()`], which is used to generated [`RepositoryCollection`].
#[derive(Debug)]
pub struct RepositoryCollector;
impl RepositoryCollector {
/// Generate [`RepositoryCollection`] for a given path and its children.
pub fn run(
path: &Path,
include_email: bool,
include_submodules: bool,
) -> CollectorResult<RepositoryCollection> {
let unprocessed = TargetCollector::run(path.to_path_buf())?
.par_iter()
.map(|path| RepositoryView::new(path, include_email, include_submodules))
.collect::<Vec<UnprocessedRepositoryView>>();
let mut processed = RepositoryCollection::new();
for maybe_view in unprocessed {
match maybe_view {
Ok(view) => {
if let Some(mut views) =
processed.insert(view.parent.clone(), vec![view.clone()])
{
views.push(view.clone());
processed.insert(view.parent, views);
}
}
Err(e) => return Err(e.into()),
}
}
Ok(processed)
}
}
|