Skip to main content

FollowsGraph

Struct FollowsGraph 

Source
pub struct FollowsGraph { /* private fields */ }
Expand description

Index of follows Edges keyed by their source path. Construct with Self::from_declared, Self::from_lock, or Self::from_flake for declared-only, resolved-only, or merged views respectively.

Implementations§

Source§

impl FollowsGraph

Source

pub fn from_declared(inputs: &InputMap) -> Self

Build a graph from the declared inputs = { ... } block alone.

Each Follows::Indirect in inputs becomes one EdgeOrigin::Declared edge carrying Input::range.

Source

pub fn from_lock(lock: &FlakeLock) -> Self

Build a graph from the lockfile alone.

Walks flake.lock from the root once via FlakeLock::nested_inputs and defers to Self::from_nested_inputs.

Source

pub fn from_nested_inputs(nested_inputs: &[NestedInput]) -> Self

Build the lock graph from an already-computed nested-input set.

Emits one EdgeOrigin::Resolved edge per inputs.X = ["a", "b", ...] follows override, bounded by DEFAULT_MAX_DEPTH. Every nested-input path is recorded in resolved_universe, with or without a follows.

Takes the precomputed slice so a single FlakeLock::nested_inputs walk can feed every consumer in one invocation.

Source

pub fn from_flake(inputs: &InputMap, lock: &FlakeLock) -> Self

Build the merged graph: declared edges first, then resolved edges from the lockfile that no existing edge already covers at the same (source, follows). Every nested-input path observed in the lockfile is recorded in resolved_universe.

Dedup is by (source, follows), not by source alone: a declared edge and its resolved sibling can share a source but point at different targets (the user’s depth-N follow points at the user’s top-level input; the lockfile points at the upstream’s intermediate path). Both encode distinct reachability and Self::lock_routes_to needs the resolved sibling to survive when the declared edge is excluded as a candidate.

Source

pub fn with_max_depth(self, max: usize) -> Self

Override the traversal depth bound. Default is DEFAULT_MAX_DEPTH.

Source

pub fn outgoing(&self, src: &AttrPath) -> &[Edge]

Outgoing edges from src, or an empty slice.

Source

pub fn edges(&self) -> impl Iterator<Item = &Edge>

Iterator over every edge.

Order is unspecified (HashMap-derived). Callers that need a deterministic order must sort after collecting.

Source

pub fn declared_edges(&self) -> impl Iterator<Item = &Edge>

Edges originating from flake.nix. See Self::edges on ordering.

Source

pub fn declared_sources(&self) -> HashSet<AttrPath>

Every source path the user has declared a follows for in flake.nix, regardless of whether it resolves to a target. The union of Self::declared_edges sources and the nulled (follows = "") sources tracked alongside them.

Distinct from Self::declared_edges because the auto-follow pipeline must treat a nulled declaration as “already user-owned” and skip it; the edges-only view drops nulled sources because they have no target to put on the right-hand side of an edge.

Source

pub fn declared_nulled(&self) -> &HashSet<AttrPath>

Read-only view of source paths declared as follows = "". The auto-deduplicator consults this to distinguish a nulled declaration (user explicitly opted out) from a path with a real follows target.

Source

pub fn cycles(&self) -> Vec<Cycle>

Cycles among declared edges only: detects per-segment self-cycles where an edge’s source equals its follows. Multi-hop and lockfile-only cycle detection lives on Self::would_create_cycle.

Source

pub fn stale_edges(&self) -> Vec<&Edge>

Declared edges whose source path no longer appears in the lockfile. A follows declaration whose nested input is gone from flake.lock should be dropped on the next auto-follow pass. Lex-sorted by source.

Source

pub fn stale_nulled_sources(&self) -> Vec<&AttrPath>

Sibling of Self::stale_edges for Self::declared_nulled: nulled (follows = "") declarations whose source is absent from resolved_universe. A nulled declaration backed by an inputs.X = [] lock entry stays in resolved_universe and is not reported. Lex-sorted.

Source

pub fn stale_lock_declarations<'a>( &'a self, nested_inputs: &[NestedInput], ) -> Vec<StaleLockDeclaration<'a>>

Declared follows whose target disagrees with the lockfile’s resolution for the same source path.

A returned entry means flake.nix declares a follows for entry.declared.source pointing at entry.declared.follows, but the lock has either:

  • lock_target = Some(other): a different resolved target, or
  • lock_target = None: no follows at all (override never applied).

Both cases call for nix flake lock. Sources missing from the lockfile entirely are reported by Self::stale_edges instead.

Lex-sorted by source.

Source

pub fn would_create_cycle(&self, proposed: &Edge) -> bool

Whether adding proposed would close a follows cycle.

Origin-agnostic DFS from proposed.follows. Reaching proposed.source means the new edge closes a cycle. Beyond the trivial self-edge case, three classes are covered:

  1. Dot-named ancestor. AttrPath equality is structural, so a participant like "hls-1.10" compares by its unquoted segment value, not by URL prefix.
  2. Multi-hop chains. A cycle A → B → C → ... → A is found by walking the chain.
  3. Lockfile-only cycles. EdgeOrigin::Resolved edges are traversed alongside declared ones, so a chain closing only through the lockfile is still reported.

Bounded by Self::with_max_depth for malformed graphs. Standard visited / on-stack sets keep pre-existing cycles from wedging the walk.

Source

pub fn drop_edges_with_sources(&mut self, sources: &[AttrPath])

Drop every edge whose source is in sources.

Hides a known set of edges from Self::would_create_cycle and Self::lock_routes_to without re-deriving the graph from scratch. resolved_universe is intentionally untouched: removing a declared edge does not retroactively unobserve the lockfile path the source was discovered from.

Source

pub fn lock_routes_to( &self, source: &AttrPath, target: &AttrPath, exclude: Option<&Edge>, extra_edges: &[(AttrPath, AttrPath)], ) -> bool

Whether the graph routes source transitively to target, ignoring exclude if given. extra_edges are treated as additional declared-style edges for callers staging follows not yet in the graph.

Walks both EdgeOrigin::Declared and EdgeOrigin::Resolved edges: Self::from_flake keeps only one when both encode the same (source, target), so restricting the walk to one variant would miss chains closing through the deduped edge.

Trait Implementations§

Source§

impl Clone for FollowsGraph

Source§

fn clone(&self) -> FollowsGraph

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for FollowsGraph

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for FollowsGraph

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more