Class: DepSelector::Package

Inherits:
Object
  • Object
show all
Defined in:
lib/dep_selector/package.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dependency_graph, name) ⇒ Package

Returns a new instance of Package.



27
28
29
30
31
# File 'lib/dep_selector/package.rb', line 27

def initialize(dependency_graph, name)
  @dependency_graph = dependency_graph
  @name = name
  @versions = []
end

Instance Attribute Details

#dependency_graphObject (readonly)

Returns the value of attribute dependency_graph.



25
26
27
# File 'lib/dep_selector/package.rb', line 25

def dependency_graph
  @dependency_graph
end

#nameObject (readonly)

Returns the value of attribute name.



25
26
27
# File 'lib/dep_selector/package.rb', line 25

def name
  @name
end

#versionsObject (readonly)

Returns the value of attribute versions.



25
26
27
# File 'lib/dep_selector/package.rb', line 25

def versions
  @versions
end

Instance Method Details

#[](version_or_constraint) ⇒ Object

Given a version, this method returns the corresonding PackageVersion. Given a version constraint, this method returns an array of matching PackageVersions. – TODO [cw,2011/2/4]: rationalize this with DenselyPackedSet#[]



48
49
50
51
52
53
54
55
56
57
# File 'lib/dep_selector/package.rb', line 48

def [](version_or_constraint)
  # version constraints must abide the include? contract
  if version_or_constraint.respond_to?(:include?)
    versions.select do |ver|
      version_or_constraint.include?(ver)
    end
  else
    versions.find{|pkg_version| pkg_version.version == version_or_constraint}
  end
end

#add_version(version) ⇒ Object



33
34
35
36
# File 'lib/dep_selector/package.rb', line 33

def add_version(version)
  versions << (pv = PackageVersion.new(self, version))
  pv
end

#densely_packed_versionsObject

Note: only invoke this method after all PackageVersions have been added



39
40
41
# File 'lib/dep_selector/package.rb', line 39

def densely_packed_versions
  @densely_packed_versions ||= DenselyPackedSet.new(versions.map{|pkg_version| pkg_version.version})
end

#eql?(o) ⇒ Boolean Also known as: ==

Returns:

  • (Boolean)


108
109
110
111
112
# File 'lib/dep_selector/package.rb', line 108

def eql?(o)
  # TODO [cw,2011/2/7]: this is really shallow. should implement
  # == for DependencyGraph
  self.class == o.class && name == o.name
end

#gecode_package_idObject

Note: only invoke this method after all PackageVersions have been added



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/dep_selector/package.rb', line 75

def gecode_package_id
  # Note: gecode does naive bounds propagation at every post,
  # which means that any package with exactly one version is
  # considered bound and its dependencies propagated even though
  # there might not be a solution constraint that requires that
  # package to be bound, which means that otherwise-irrelevant
  # constraints (e.g. A1->B1 when the solution constraint is B=2
  # and there is nothing to induce a dependency on A) can cause
  # unsatisfiability. Therefore, we want every package to have at
  # least two versions, one of which is neither the target of
  # other packages' dependencies nor induces other
  # dependencies. Package version id -1 serves this purpose.
  #
  # TODO [cw, 2011/2/22]: Do we likewise want to leave packages
  # with no versions (the target of an invalid dependency) with
  # two versions in order to allow the solver to explore the
  # invalid portion of the state space instead of naively limiting
  # it for the purposes of having failure count heuristics?
  max = densely_packed_versions.range.max || -1
  @gecode_package_id ||= dependency_graph.gecode_wrapper.add_package(-1, max, 0)
end

#generate_gecode_wrapper_constraintsObject



97
98
99
100
101
102
103
104
105
106
# File 'lib/dep_selector/package.rb', line 97

def generate_gecode_wrapper_constraints
  # if this is a valid package (has versions), we don't need to
  # explicitly call gecode_package_id, because they will do it for
  # us; however, if this package isn't valid (it only exists as an
  # invalid dependency and thus has no versions), the solver gets
  # confused, because we won't have generated its package id by
  # the time it starts solving.
  gecode_package_id
  versions.each{|version| version.generate_gecode_wrapper_constraints }
end

#to_s(incl_densely_packed_versions = false) ⇒ Object



64
65
66
67
68
69
70
71
72
# File 'lib/dep_selector/package.rb', line 64

def to_s(incl_densely_packed_versions = false)
  components = []
  components << "Package #{name}"
  if incl_densely_packed_versions
    components << " (#{densely_packed_versions.range})"
  end
  versions.each{|version| components << "\n  #{version.to_s(incl_densely_packed_versions)}"}
  components.flatten.join
end

#valid?Boolean

A Package is considered valid if it has at least one version

Returns:

  • (Boolean)


60
61
62
# File 'lib/dep_selector/package.rb', line 60

def valid?
  versions.any?
end