Skip to main content

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}