Class: Vendor::VendorFile::DependencyGraph

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(libs = nil) ⇒ DependencyGraph



9
10
11
# File 'lib/vendor/vendor_file/dependency_graph.rb', line 9

def initialize(libs = nil)
  self.libraries = libs
end

Instance Attribute Details

#librariesObject

Returns the value of attribute libraries.



6
7
8
# File 'lib/vendor/vendor_file/dependency_graph.rb', line 6

def libraries
  @libraries
end

#libraries_to_installObject (readonly)

Returns the value of attribute libraries_to_install.



7
8
9
# File 'lib/vendor/vendor_file/dependency_graph.rb', line 7

def libraries_to_install
  @libraries_to_install
end

Instance Method Details

#dependency_graphObject



23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/vendor/vendor_file/dependency_graph.rb', line 23

def dependency_graph
  map = {}
  _touched = {}
  graph = []
  @libraries.each do |lib|
    if (x = _map(lib, map, _touched))
      graph << x
    end
  end

  return graph, map
end

#version_conflicts?Boolean



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/vendor/vendor_file/dependency_graph.rb', line 36

def version_conflicts?
  graph, map = dependency_graph

  # The version conflict detector is pretty stupid, pretty much if
  # two libraries are trying to include a lib of different
  # versions:
  # a requires b v1.0
  # c requires b v1.1
  # Then things will blow up.

  @libraries_to_install = []

  map.keys.sort.each do |name|

    libs = map[name]

    # Only populate the "targets" element if there is a specific
    # target to add to.
    found_targets = libs.find_all { |l| l.targets if l.targets }.map &:targets
    targets = found_targets.empty? ? nil : found_targets.flatten.compact.uniq

    version_to_install = libs.first

    # Check for conflicts and try to resolve
    if libs.length > 1

      # Sort the versions, starting with the latest version first
      versions = libs.sort.reverse

      # This code is a little yucky, but what it does, is it tries
      # to find the best version match for every other version in
      # the loop. So, lets say we have versions => 0.1 and ~> 0.1,
      # and we have an array of [ "0.1", "0.1.1" ], try and find
      # the higest versiont that each likes. Once we know that, we
      # uniqify the results. If we have more than 1, that means we
      # have a conflict.
      vvs = versions.map(&:version)
      matched_versions = libs.map do |l|
        l.version_matches_any?(vvs)
      end.inject([]) do |uniqs, obj|
        if uniqs.all? { |e| e != obj }
          uniqs << obj
        end
        uniqs
      end

      if matched_versions.length > 1
        version_to_install = nil
      else
        # Find the version we've recomended and install that one.
        y = matched_versions.first
        version_to_install = versions.find do |x|
          x.version == y.to_s
        end
      end

    end

    # Are there multiple versions to install?
    unless version_to_install
      Vendor.ui.error "Multiple versions detected for #{name} (#{versions.map(&:version).join(', ')})"

      # A semi-meaningfull error
      libs.each do |v|
        if v.parent
          Vendor.ui.error "  #{v.description} is required by #{v.parent.description}"
        else
          Vendor.ui.error "  #{v.description} is required in the Vendorfile"
        end
      end

      exit
    else
      @libraries_to_install << [ version_to_install, targets ]
    end
  end

  false
end