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.

Parameters:

  • version_range (SemanticPuppet::VersionRange, String, nil)

    the version range to convert

Returns:

  • (SemanticPuppet::VersionRange)

    the converted version range

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

Parameters:

  • a (SemanticPuppet::VersionRange)

    the first range

  • b (SemanticPuppet::VersionRange)

    the second range

Returns:

  • (Boolean)

    ‘true` if a is completely covered by 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`

Parameters:

  • range (SemanticPuppet::VersionRange)

    the range to match against

  • version (SemanticPuppet::Version, String)

    the version to match

Returns:

  • (Boolean)

    ‘true` if the range includes the given version



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.

Parameters:

  • a (SemanticPuppet::VersionRange)

    the first range

  • b (SemanticPuppet::VersionRange)

    the second range

Returns:

  • (SemanticPuppet::VersionRange, nil)

    the result of the merge



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

Returns:

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

Returns:

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

Returns:

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

Returns:

  • (Boolean)


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

def roundtrip_with_string?
  true
end