Class: Bundler::Stats::Remover

Inherits:
Object
  • Object
show all
Defined in:
lib/bundler/stats/remover.rb

Constant Summary collapse

ERR_MESSAGE =
"Trying to check whether dep can be removed, but was unable " \
"to resolve whether it is used by `%s`. It may not be in your Gemfile.lock. " \
"This often happens when a dependency isn't installed on your platform."

Instance Method Summary collapse

Constructor Details

#initialize(tree, top_level) ⇒ Remover

Returns a new instance of Remover.



6
7
8
9
10
# File 'lib/bundler/stats/remover.rb', line 6

def initialize(tree, top_level)
  @tree           = tree
  @top_level      = top_level
  @trace_warnings = []
end

Instance Method Details

#potential_removals(target) ⇒ Object



12
13
14
15
16
17
# File 'lib/bundler/stats/remover.rb', line 12

def potential_removals(target)
  candidates = @tree.transitive_dependencies(target)
  candidates.reject do |candidate|
    still_used?(candidate.name, deleted: target)
  end
end

#still_used?(target, deleted: nil) ⇒ Boolean

TODO: woo naive algorithm TODO: circular dependencies would be an issue here TODO: also probably use something like transitive_dependencies to leverage the abilities in tree…

Returns:

  • (Boolean)


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/bundler/stats/remover.rb', line 23

def still_used?(target, deleted: nil)
  modified_tree = @tree.tree.clone
  modified_tree.delete(deleted)

  deps_to_check = (@top_level - [Gem::Dependency.new(deleted)])

  while !deps_to_check.empty? do
    candidate = deps_to_check.pop.name

    next if candidate == deleted
    next if candidate == "bundler"
    return true if candidate == target

    if modified_tree[candidate].nil?
      warn_of_bad_tracing(candidate)
    else
      deps_to_check += modified_tree[candidate].dependencies
    end
  end

  false
end