grex_core/tree/error.rs
1//! Error taxonomy for the [`crate::tree`] walker.
2//!
3//! Errors carry `PathBuf` and `String` detail fields rather than boxing
4//! underlying loader or parser errors. Keeping leaky types out of the public
5//! surface means adding a new loader backend (IPC, in-memory, http) in a
6//! future slice stays non-breaking.
7
8use std::path::PathBuf;
9
10use thiserror::Error;
11
12use crate::git::GitError;
13
14/// Errors raised during a pack-tree walk.
15///
16/// Marked `#[non_exhaustive]` so later slices (credentials, submodules,
17/// partial walks) can add variants without breaking consumers.
18#[non_exhaustive]
19#[derive(Debug, Error)]
20pub enum TreeError {
21 /// The walker expected a `pack.yaml` at the given location but could not
22 /// find one (or its enclosing `.grex/` directory was missing).
23 #[error("pack manifest not found at `{0}`")]
24 ManifestNotFound(PathBuf),
25
26 /// The manifest file existed but could not be read from disk.
27 #[error("failed to read pack manifest: {0}")]
28 ManifestRead(String),
29
30 /// The manifest file was read but did not parse as a valid `pack.yaml`.
31 #[error("failed to parse pack manifest at `{path}`: {detail}")]
32 ManifestParse {
33 /// On-disk location of the manifest that failed to parse.
34 path: PathBuf,
35 /// Backend-provided failure detail.
36 detail: String,
37 },
38
39 /// A git operation (clone, fetch, checkout, …) failed while hydrating a
40 /// child pack. The underlying [`GitError`] is preserved in full.
41 #[error("git error during walk: {0}")]
42 Git(#[from] GitError),
43
44 /// A cycle was detected during the walk. `chain` lists the pack URLs (or
45 /// paths for the root) from the outermost pack down to the recurrence.
46 #[error("cycle detected in pack graph: {chain:?}")]
47 CycleDetected {
48 /// Ordered chain of pack identities that forms the cycle.
49 chain: Vec<String>,
50 },
51
52 /// A cloned child's `pack.yaml` declared a `name` that does not match
53 /// what the parent pack expected for that `children:` entry.
54 #[error("pack name `{got}` does not match expected `{expected}` for child at `{path}`")]
55 PackNameMismatch {
56 /// Name declared in the child's own manifest.
57 got: String,
58 /// Name the parent expected (derived from the child entry's
59 /// effective path).
60 expected: String,
61 /// On-disk location of the offending child.
62 path: PathBuf,
63 },
64}