Class: Bundler::Stats::Tree

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

Constant Summary collapse

ERR_MESSAGE =
"The dependency `%s` wasn't found. It may not be present in " \
"your Gemfile.lock. This often happens when a dependency isn't " \
"installed on your platform."

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parser, skiplist: '') ⇒ Tree

Returns a new instance of Tree.

Raises:

  • (ArgumentError)


8
9
10
11
12
13
14
# File 'lib/bundler/stats/tree.rb', line 8

def initialize(parser, skiplist: '')
  raise ArgumentError unless parser.respond_to?(:specs)

  @parser   = parser
  @tree     = specs_as_tree(@parser.specs)
  @skiplist = Bundler::Stats::Skiplist.new(skiplist)
end

Instance Attribute Details

#skiplistObject

Returns the value of attribute skiplist.



2
3
4
# File 'lib/bundler/stats/tree.rb', line 2

def skiplist
  @skiplist
end

#treeObject

Returns the value of attribute tree.



2
3
4
# File 'lib/bundler/stats/tree.rb', line 2

def tree
  @tree
end

Instance Method Details

#first_level_dependencies(target) ⇒ Object



40
41
42
43
44
45
46
47
# File 'lib/bundler/stats/tree.rb', line 40

def first_level_dependencies(target)
  unless @tree.has_key? target
    warn(ERR_MESSAGE % [target])
    return []
  end

  @tree[target].dependencies
end

#reverse_dependencies(target) ⇒ Object

TODO: this is a very stupid way to walk this tree



69
70
71
72
73
74
# File 'lib/bundler/stats/tree.rb', line 69

def reverse_dependencies(target)
  @tree.select do |name, dep|
    all_deps = transitive_dependencies(name)
    all_deps.any? { |dep| dep.name == target }
  end
end

#reverse_dependencies_with_versions(target) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/bundler/stats/tree.rb', line 76

def reverse_dependencies_with_versions(target)
  @tree.map do |name, dep|
    transitive_dependencies(name).map do |transitive_dependency|
      if transitive_dependency.name == target
        {
          name: dep.name,
          version: transitive_dependency.requirement.to_s,
          requirement: transitive_dependency.requirement
        }
      else
        nil
      end
    end
  end.flatten.compact.sort do |a,b|
    a[:requirement].as_list <=> b[:requirement].as_list
  end
end

#summarize(target) ⇒ Object



16
17
18
19
20
21
22
23
24
25
# File 'lib/bundler/stats/tree.rb', line 16

def summarize(target)
  transitive_dependencies = transitive_dependencies(target)

  { name: target,
    total_dependencies: transitive_dependencies.count,
    first_level_dependencies: first_level_dependencies(target).count,
    top_level_dependencies: reverse_dependencies(target),
    transitive_dependencies: transitive_dependencies,
  }
end

#transitive_dependencies(target) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/bundler/stats/tree.rb', line 49

def transitive_dependencies(target)
  unless @tree.has_key? target
    warn(ERR_MESSAGE % [target])
    return []
  end

  top_level = skiplist.filter(@tree[target].dependencies)
  all_level = top_level + top_level.inject([]) do |arr, dep|
    # turns out bundler refuses to include itself in the dependency tree,
    # which is sneaky
    next arr if dep.name == "bundler"
    next arr if skiplist.include? dep

    arr += transitive_dependencies(dep.name)
  end

  all_level.uniq { |d| d.name }
end

#version_requirements(target) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/bundler/stats/tree.rb', line 27

def version_requirements(target)
  transitive_dependencies = transitive_dependencies(target)
  resolved_version = @tree[target].version if @tree.has_key?(target)

  { name: target,
    resolved_version: resolved_version,
    total_dependencies: transitive_dependencies.count,
    first_level_dependencies: first_level_dependencies(target).count,
    top_level_dependencies: reverse_dependencies_with_versions(target),
    transitive_dependencies: transitive_dependencies,
  }
end