Skip to main content

objects/blame/
run.rs

1// SPDX-License-Identifier: Apache-2.0
2//! One-shot blame that loops storage-neutral slices until complete.
3
4use std::path::Path;
5
6use crate::object::{FileProvenance, ObjectSource, State};
7
8use super::{
9    advance::advance_file_blame_slice,
10    finalize::finalize_file_provenance,
11    prepare::prepare_file_blame,
12    types::{
13        BlamePreparation, BlameSliceAdvance, BlameSliceError, BlameSliceLimits, BlameTarget,
14        OriginRange,
15    },
16};
17
18/// Walk `path` at `state` by repeating [`advance_file_blame_slice`] until the
19/// frontier is exhausted, then finalize. This is not an eager full-file shim;
20/// each slice stays inside `limits`.
21pub fn blame_file<S: ObjectSource>(
22    source: &S,
23    state: &State,
24    path: &Path,
25    limits: BlameSliceLimits,
26) -> Result<FileProvenance, BlameSliceError> {
27    match prepare_file_blame(source, state, path, limits)? {
28        BlamePreparation::MissingPath => Err(BlameSliceError::MissingPath),
29        BlamePreparation::Unblamable => Err(BlameSliceError::Unblamable),
30        BlamePreparation::Empty { file_blob, origin } => finalize_file_provenance(
31            file_blob,
32            0,
33            [OriginRange {
34                target_start: 0,
35                len: 0,
36                origin,
37            }],
38        ),
39        BlamePreparation::Active {
40            file_blob,
41            line_count,
42            mut frontier,
43        } => {
44            let expected = BlameTarget::bind(state.id(), path, file_blob, line_count)?;
45            frontier.require_target(&expected)?;
46            let mut finalized = Vec::new();
47            loop {
48                frontier.require_target(&expected)?;
49                match advance_file_blame_slice(source, path, frontier, limits)? {
50                    BlameSliceAdvance::Progress {
51                        next,
52                        finalized: more,
53                        ..
54                    } => {
55                        finalized.extend(more);
56                        frontier = next;
57                    }
58                    BlameSliceAdvance::Complete {
59                        finalized: more, ..
60                    } => {
61                        finalized.extend(more);
62                        break;
63                    }
64                }
65            }
66            finalize_file_provenance(file_blob, line_count, finalized)
67        }
68    }
69}