Class: GemCP::DependencyGraph

Inherits:
Object
  • Object
show all
Defined in:
lib/gemcp/dependency_graph.rb

Overview

Builds a bounded exploratory dependency graph by traversing RubyGems metadata. This is NOT a lockfile resolver — it follows each dependency's latest release and preserves version constraints on edges for informational purposes only.

Constant Summary collapse

MAX_DEPTH =
4
MAX_NODES =
100

Instance Method Summary collapse

Constructor Details

#initialize(client:) ⇒ DependencyGraph

Returns a new instance of DependencyGraph.

Parameters:

  • client (Client)

    the API client to fetch version metadata



14
15
16
# File 'lib/gemcp/dependency_graph.rb', line 14

def initialize(client:)
  @client = client
end

Instance Method Details

#build(name:, version: nil, platform: nil, depth: 1, include_development: false) ⇒ Hash

Build the dependency graph starting from a root gem.

Parameters:

  • name (String)

    root gem name

  • version (String, nil) (defaults to: nil)

    root version (defaults to latest)

  • platform (String, nil) (defaults to: nil)

    platform filter for the root

  • depth (Integer) (defaults to: 1)

    traversal depth (clamped to 0..MAX_DEPTH)

  • include_development (Boolean) (defaults to: false)

    whether to follow dev dependencies

Returns:

  • (Hash)

    graph with :root, :nodes, :edges, :truncated, :limits



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/gemcp/dependency_graph.rb', line 26

def build(name:, version: nil, platform: nil, depth: 1, include_development: false)
  depth = Integer(depth).clamp(0, MAX_DEPTH)
  root_version = version || @client.latest_version(name).fetch("version")
  state = { nodes: {}, edges: [], visited: Set.new, truncated: false }

  visit(
    name: name,
    version: root_version,
    platform: platform,
    depth_remaining: depth,
    include_development: include_development,
    state: state
  )

  {
    root: { name: name, version: root_version, platform: platform },
    nodes: state[:nodes].values,
    edges: state[:edges],
    truncated: state[:truncated],
    limits: { max_depth: MAX_DEPTH, max_nodes: MAX_NODES }
  }
end