Class: Gemchain::DependencyGraph

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

Defined Under Namespace

Classes: CircularDependencyError

Instance Method Summary collapse

Constructor Details

#initialize(gems) ⇒ DependencyGraph

Returns a new instance of DependencyGraph.



7
8
9
10
# File 'lib/gemchain/dependency_graph.rb', line 7

def initialize(gems)
  @gems = gems
  @graph = build_graph
end

Instance Method Details

#cascade_order(start_gem = nil) ⇒ Object

Topological order: dependencies before dependents. If start_gem is given, only includes that gem and its transitive dependents.



48
49
50
51
52
53
54
55
56
# File 'lib/gemchain/dependency_graph.rb', line 48

def cascade_order(start_gem = nil)
  if start_gem
    relevant = transitive_dependents(start_gem)
    subgraph = @graph.select { |k, _| relevant.include?(k) }
    tsort(subgraph)
  else
    tsort(@graph)
  end
end

#dependencies_of(gem_name) ⇒ Object

Gems that gem_name directly depends on (only workspace gems).



18
19
20
21
22
23
# File 'lib/gemchain/dependency_graph.rb', line 18

def dependencies_of(gem_name)
  gem = find(gem_name)
  return [] unless gem

  gem.dependencies.keys.filter_map { |dep_name| find(dep_name) }
end

#dependents_of(gem_name) ⇒ Object

Gems that directly depend on gem_name.



13
14
15
# File 'lib/gemchain/dependency_graph.rb', line 13

def dependents_of(gem_name)
  @gems.select { |g| g.dependencies.key?(gem_name) }
end

#leaf_gemsObject

Gems with no workspace dependencies — leaves of the dependency tree.



42
43
44
# File 'lib/gemchain/dependency_graph.rb', line 42

def leaf_gems
  @gems.select { |g| dependencies_of(g.name).empty? }
end

#transitive_dependents(gem_name) ⇒ Object

All transitive dependents of gem_name, including the gem itself.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/gemchain/dependency_graph.rb', line 26

def transitive_dependents(gem_name)
  result = Set.new
  queue = [gem_name]

  until queue.empty?
    current = queue.shift
    next if result.include?(current)

    result.add(current)
    dependents_of(current).each { |g| queue << g.name }
  end

  result.to_a
end