Class: Puppet::Pops::Types::PSemVerRangeType

Inherits:
PAnyType show all
Defined in:
lib/puppet/pops/types/p_sem_ver_range_type.rb

Overview

An unparameterized type that represents all VersionRange instances

Constant Summary collapse

DEFAULT =
PSemVerRangeType.new

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from PAnyType

#==, #accept, #assignable?, #callable?, #callable_args?, #callable_with?, #check_self_recursion, create, #create, #generalize, #hash, #iterable?, #iterable_type, #kind_of_callable?, #loader, #name, #new_function, #normalize, #really_instance?, #resolve, #simple_name, simple_name, #to_alias_expanded_s, #to_s

Methods inherited from TypedModelObject

_pcore_type, create_ptype, register_ptypes

Methods included from Visitable

#accept

Methods included from PuppetObject

#_pcore_all_contents, #_pcore_contents, #_pcore_init_hash, #_pcore_type, #to_s

Class Method Details

.convert(version_range) ⇒ SemanticPuppet::VersionRange

Creates a SemanticPuppet::VersionRange from the given version_range argument. If the argument is `nil` or a SemanticPuppet::VersionRange, it is returned. If it is a String, it will be parsed into a SemanticPuppet::VersionRange. Any other class will raise an ArgumentError.

Raises:

  • (ArgumentError)

    when the argument cannot be converted into a version range


43
44
45
46
47
48
49
50
51
52
# File 'lib/puppet/pops/types/p_sem_ver_range_type.rb', line 43

def self.convert(version_range)
  case version_range
  when nil, SemanticPuppet::VersionRange
    version_range
  when String
    SemanticPuppet::VersionRange.parse(version_range)
  else
    raise ArgumentError, "Unable to convert a #{version_range.class.name} to a SemVerRange"
  end
end

.covered_by?(a, b) ⇒ Boolean

Checks if range a is a sub-range of (i.e. completely covered by) range b


59
60
61
# File 'lib/puppet/pops/types/p_sem_ver_range_type.rb', line 59

def self.covered_by?(a, b)
  b.begin <= a.begin && (b.end > a.end || b.end == a.end && (!b.exclude_end? || a.exclude_end?))
end

.include?(range, version) ⇒ Boolean

Check if a version is included in a version range. The version can be a string or a `SemanticPuppet::SemVer`


20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/puppet/pops/types/p_sem_ver_range_type.rb', line 20

def self.include?(range, version)
  case version
  when SemanticPuppet::Version
    range.include?(version)
  when String
    begin
      range.include?(SemanticPuppet::Version.parse(version))
    rescue SemanticPuppet::Version::ValidationFailure
      false
    end
  else
    false
  end
end

.merge(a, b) ⇒ SemanticPuppet::VersionRange?

Merge two ranges so that the result matches all versions matched by both. A merge is only possible when the ranges are either adjacent or have an overlap.


71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/puppet/pops/types/p_sem_ver_range_type.rb', line 71

def self.merge(a, b)
  if a.include?(b.begin) || b.include?(a.begin)
    max = [a.end, b.end].max
    exclude_end = false
    if a.exclude_end?
      exclude_end = max == a.end && (max > b.end || b.exclude_end?)
    elsif b.exclude_end?
      exclude_end = max == b.end && (max > a.end || a.exclude_end?)
    end
    SemanticPuppet::VersionRange.new([a.begin, b.begin].min, max, exclude_end)
  elsif a.exclude_end? && a.end == b.begin
    # Adjacent, a before b
    SemanticPuppet::VersionRange.new(a.begin, b.end, b.exclude_end?)
  elsif b.exclude_end? && b.end == a.begin
    # Adjacent, b before a
    SemanticPuppet::VersionRange.new(b.begin, a.end, a.exclude_end?)
  else
    # No overlap
    nil
  end
end

.new_function(type) ⇒ Object


109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/puppet/pops/types/p_sem_ver_range_type.rb', line 109

def self.new_function(type)
  @new_function ||= Puppet::Functions.create_loaded_function(:new_VersionRange, type.loader) do
    local_types do
      type 'SemVerRangeString = String[1]'
      type 'SemVerRangeHash = Struct[{min=>Variant[Default,SemVer],Optional[max]=>Variant[Default,SemVer],Optional[exclude_max]=>Boolean}]'
    end

    # Constructs a VersionRange from a String with a format specified by
    #
    # https://github.com/npm/node-semver#range-grammar
    #
    # The logical or || operator is not implemented since it effectively builds
    # an array of ranges that may be disparate. The {{SemanticPuppet::VersionRange}} inherits
    # from the standard ruby range. It must be possible to describe that range in terms
    # of min, max, and exclude max.
    #
    # The Puppet Version type is parameterized and accepts multiple ranges so creating such
    # constraints is still possible. It will just require several parameters rather than one
    # parameter containing the '||' operator.
    #
    dispatch :from_string do
      param 'SemVerRangeString', :str
    end

    # Constructs a VersionRange from a min, and a max version. The Boolean argument denotes
    # whether or not the max version is excluded or included in the range. It is included by
    # default.
    #
    dispatch :from_versions do
      param 'Variant[Default,SemVer]', :min
      param 'Variant[Default,SemVer]', :max
      optional_param 'Boolean', :exclude_max
    end

    # Same as #from_versions but each argument is instead given in a Hash
    #
    dispatch :from_hash do
      param 'SemVerRangeHash', :hash_args
    end

    def from_string(str)
      SemanticPuppet::VersionRange.parse(str)
    end

    def from_versions(min, max = :default, exclude_max = false)
      min = SemanticPuppet::Version::MIN if min == :default
      max = SemanticPuppet::Version::MAX if max == :default
      SemanticPuppet::VersionRange.new(min, max, exclude_max)
    end

    def from_hash(hash)
      from_versions(hash['min'], hash.fetch('max') { :default }, hash.fetch('exclude_max') { false })
    end
  end
end

.register_ptype(loader, ir) ⇒ Object


8
9
10
# File 'lib/puppet/pops/types/p_sem_ver_range_type.rb', line 8

def self.register_ptype(loader, ir)
  create_ptype(loader, ir, 'AnyType')
end

Instance Method Details

#eql?(o) ⇒ Boolean


101
102
103
# File 'lib/puppet/pops/types/p_sem_ver_range_type.rb', line 101

def eql?(o)
  self.class == o.class
end

#hash?Boolean


105
106
107
# File 'lib/puppet/pops/types/p_sem_ver_range_type.rb', line 105

def hash?
  super ^ @version_range.hash
end

#instance?(o, guard = nil) ⇒ Boolean


97
98
99
# File 'lib/puppet/pops/types/p_sem_ver_range_type.rb', line 97

def instance?(o, guard = nil)
  o.is_a?(SemanticPuppet::VersionRange)
end

#roundtrip_with_string?Boolean


93
94
95
# File 'lib/puppet/pops/types/p_sem_ver_range_type.rb', line 93

def roundtrip_with_string?
  true
end