1mod git_projection;
5mod objects;
6mod refs;
7mod state;
8#[cfg(test)]
9mod tests;
10
11use ::objects::{HeddleError, error::Result};
12use schemars::JsonSchema;
13use serde::Serialize;
14
15use crate::{ExecutionContext, HeddleReport, MachineOutputKind, ReportContract, schema_for_report};
16
17#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
18pub struct FsckOptions {
19 pub full: bool,
20 pub thorough: bool,
21 pub git_projection: bool,
22}
23
24#[derive(Debug, Clone, Serialize, JsonSchema, PartialEq, Eq)]
25pub struct FsckReport {
26 pub valid: bool,
27 pub errors: Vec<FsckError>,
28 pub warnings: Vec<String>,
29 pub objects_checked: usize,
30 pub git_projection_checked: bool,
31 pub repair_target: Option<String>,
32 pub repaired: bool,
33 pub repairs: Vec<FsckRepair>,
34}
35
36impl FsckReport {
37 pub const CONTRACT: ReportContract = ReportContract {
38 schema_name: "fsck",
39 machine_output_kind: MachineOutputKind::Json,
40 output_discriminator: None,
41 schema: schema_for_report::<FsckReport>,
42 };
43}
44
45impl HeddleReport for FsckReport {
46 const CONTRACT: ReportContract = FsckReport::CONTRACT;
47}
48
49#[derive(Debug, Clone, Serialize, JsonSchema, PartialEq, Eq)]
50pub struct FsckRepair {
51 pub name: String,
52 pub repaired: bool,
53 pub detail: String,
54 pub count: usize,
55}
56
57#[derive(Debug, Clone, Serialize, JsonSchema, PartialEq, Eq)]
58pub struct FsckError {
59 pub kind: String,
60 pub message: String,
61 pub object: Option<String>,
62}
63
64fn make_error(kind: &str, message: &str, object: Option<String>) -> FsckError {
65 FsckError {
66 kind: kind.to_string(),
67 message: message.to_string(),
68 object,
69 }
70}
71
72pub fn fsck(ctx: &ExecutionContext, opts: FsckOptions) -> Result<FsckReport> {
73 let repo = ctx.require_repo()?;
74
75 let mut errors: Vec<FsckError> = Vec::new();
76 let mut warnings: Vec<String> = Vec::new();
77 let mut objects_checked: usize = 0;
78
79 state::check_states(repo, &mut errors, &mut objects_checked, opts.thorough)?;
80
81 if opts.full {
82 objects::check_tree_objects(repo, &mut errors, &mut warnings, &mut objects_checked)?;
83 }
84
85 refs::check_refs(repo, &mut errors, &mut warnings)?;
86 refs::check_merge_state(repo, &mut warnings)?;
87 if opts.git_projection {
88 git_projection::check_git_projection(
89 repo,
90 &mut errors,
91 &mut warnings,
92 &mut objects_checked,
93 )?;
94 }
95
96 let valid = errors.is_empty();
97
98 Ok(FsckReport {
99 valid,
100 errors,
101 warnings,
102 objects_checked,
103 git_projection_checked: opts.git_projection,
104 repair_target: None,
105 repaired: false,
106 repairs: Vec::new(),
107 })
108}
109
110fn invalid_fsck_config(message: impl Into<String>) -> HeddleError {
111 HeddleError::Config(message.into())
112}