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

Returns a new instance of 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

Returns:

  • (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