Skip to main content

capture_git

Function capture_git 

Source
pub fn capture_git(
    git: &AdmittedTool,
    context: &ExecutionContext<'_>,
    options: StatusOptions,
    limits: OutputLimits,
) -> Result<GitObservations, GitError>
Expand description

Observe HEAD, its tree and status, with per-query bounds and no retries.

Commands disable optional locks and the filesystem monitor. The complete environment and working directory remain explicit; Git environment/config can redirect repository selection, and callers own that admission policy. Status is opaque porcelain-v1 -z output, checked only for NUL termination. These separate observations cannot prove an atomic or reproducible build.

§Errors

Returns typed tool failures, malformed object IDs or unterminated status. Retains earlier captures and the failed query’s available evidence.

Examples found in repository?
examples/inspect_git.rs (lines 73-81)
4fn main() -> Result<(), Box<dyn std::error::Error>> {
5    use ic_host_process::provenance::{
6        IgnoreSubmodules, StatusOptions, UntrackedFiles, capture_git,
7    };
8    use ic_host_process::tool::{AdmittedTool, ExecutionContext, OutputLimits, ToolSpec};
9
10    use std::{ffi::OsString, io, path::PathBuf, time::Duration};
11
12    let invalid = |message| io::Error::new(io::ErrorKind::InvalidInput, message);
13    let mut args = std::env::args_os().skip(1);
14    let mut required = || {
15        args.next().ok_or_else(|| invalid(
16        "usage: inspect_git TOOL SHA256 VERSION WORKDIR MAX_TOOL_BYTES MAX_STDOUT_BYTES MAX_STDERR_BYTES TIMEOUT_MS UNTRACKED SUBMODULES",
17    ))
18    };
19    let executable = PathBuf::from(required()?);
20    let digest = required()?
21        .into_string()
22        .map_err(|_| invalid("digest must be UTF-8"))?
23        .parse()?;
24    let version = required()?
25        .into_string()
26        .map_err(|_| invalid("version must be UTF-8"))?;
27    let directory = PathBuf::from(required()?);
28    let mut number = || -> Result<u64, Box<dyn std::error::Error>> {
29        Ok(required()?
30            .to_str()
31            .ok_or_else(|| invalid("limits must be UTF-8"))?
32            .parse()?)
33    };
34    let executable_bytes = number()?;
35    let limits = OutputLimits {
36        stdout: ic_host_process::tool::OutputLimit::Terminate(usize::try_from(number()?)?),
37        stderr: ic_host_process::tool::OutputLimit::Terminate(usize::try_from(number()?)?),
38        timeout: Some(Duration::from_millis(number()?)),
39    };
40    let untracked = match required()?.to_str() {
41        Some("no") => UntrackedFiles::No,
42        Some("normal") => UntrackedFiles::Normal,
43        Some("all") => UntrackedFiles::All,
44        _ => return Err(invalid("untracked must be no, normal or all").into()),
45    };
46    let ignore_submodules = match required()?.to_str() {
47        Some("none") => IgnoreSubmodules::None,
48        Some("untracked") => IgnoreSubmodules::Untracked,
49        Some("dirty") => IgnoreSubmodules::Dirty,
50        Some("all") => IgnoreSubmodules::All,
51        _ => return Err(invalid("submodules must be none, untracked, dirty or all").into()),
52    };
53    if args.next().is_some() {
54        return Err(invalid("unexpected argument").into());
55    }
56    // The example explicitly selects an empty environment; the library never
57    // chooses environment exclusions or tool/version pins for a consumer.
58    let context = ExecutionContext {
59        current_dir: &directory,
60        environment: &[],
61    };
62    let git = AdmittedTool::admit(
63        &ToolSpec {
64            executable: &executable,
65            sha256: digest,
66            executable_bytes,
67            version_arguments: &[OsString::from("--version")],
68            version_identity: &version,
69        },
70        &context,
71        limits,
72    )?;
73    let observed = capture_git(
74        &git,
75        &context,
76        StatusOptions {
77            untracked,
78            ignore_submodules,
79        },
80        limits,
81    )?;
82    println!("revision={}", observed.revision);
83    println!("tree={}", observed.tree);
84    println!("dirty={}", observed.is_dirty());
85    println!("status_bytes={}", observed.status_identity.bytes);
86    println!("status_sha256={}", observed.status_identity.sha256);
87    Ok(())
88}