Class: XSemVer::SemVer

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/xsemver.rb

Overview

‘SemVer’ in global scope. Too Bad®. Use this symbol instead.

Direct Known Subclasses

SemVer

Constant Summary collapse

FILE_NAME =
'.semver'
TAG_FORMAT =
'v%M.%m.%p%s%d'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(major = 0, minor = 0, patch = 0, special = '', metadata = '') ⇒ SemVer

Returns a new instance of SemVer.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/xsemver.rb', line 42

def initialize major=0, minor=0, patch=0, special='', =''
  major.kind_of? Integer or raise "invalid major: #{major}"
  minor.kind_of? Integer or raise "invalid minor: #{minor}"
  patch.kind_of? Integer or raise "invalid patch: #{patch}"

  unless special.empty?
    special =~ /[A-Za-z][0-9A-Za-z\.]+/ or raise "invalid special: #{special}"
  end

  unless .empty?
     =~ /\A[A-Za-z0-9][0-9A-Za-z\.-]*\z/ or raise "invalid metadata: #{}"
  end

  @major, @minor, @patch, @special, @metadata = major, minor, patch, special, 
end

Instance Attribute Details

#majorObject

Returns the value of attribute major.



40
41
42
# File 'lib/xsemver.rb', line 40

def major
  @major
end

#metadataObject

Returns the value of attribute metadata.



40
41
42
# File 'lib/xsemver.rb', line 40

def 
  @metadata
end

#minorObject

Returns the value of attribute minor.



40
41
42
# File 'lib/xsemver.rb', line 40

def minor
  @minor
end

#patchObject

Returns the value of attribute patch.



40
41
42
# File 'lib/xsemver.rb', line 40

def patch
  @patch
end

#specialObject

Returns the value of attribute special.



40
41
42
# File 'lib/xsemver.rb', line 40

def special
  @special
end

Class Method Details

.file_nameObject



12
13
14
# File 'lib/xsemver.rb', line 12

def SemVer.file_name
  FILE_NAME
end

.find(dir = nil) ⇒ Object



16
17
18
19
20
21
# File 'lib/xsemver.rb', line 16

def SemVer.find dir=nil
  v = SemVer.new
  f = SemVer.find_file dir
  v.load f
  v
end

.find_file(dir = nil) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/xsemver.rb', line 23

def SemVer.find_file dir=nil
  dir ||= Dir.pwd
  raise "#{dir} is not a directory" unless File.directory? dir
  path = File.join dir, file_name

  Dir.chdir dir do
    while !File.exists? path do
      raise SemVerMissingError, "#{dir} is not semantic versioned", caller if File.dirname(path).match(/(\w:\/|\/)$/i)
      path = File.join File.dirname(path), ".."
      path = File.expand_path File.join(path, file_name)
      puts "semver: looking at #{path}"
    end
    return path
  end

end

.parse(version_string, format = nil, allow_missing = true) ⇒ Object

Parses a semver from a string and format.



108
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
# File 'lib/xsemver.rb', line 108

def self.parse(version_string, format = nil, allow_missing = true)
  format ||= TAG_FORMAT
  regex_str = Regexp.escape format

  # Convert all the format characters to named capture groups
  regex_str = regex_str.
    gsub(/^v/, 'v?').
    gsub('%M', '(?<major>\d+)').
    gsub('%m', '(?<minor>\d+)').
    gsub('%p', '(?<patch>\d+)').
    gsub('%s', '(?:-(?<special>[A-Za-z][0-9A-Za-z\.]+))?').
    gsub('%d', '(?:\\\+(?<metadata>[0-9A-Za-z][0-9A-Za-z\.]*))?')

  regex = Regexp.new(regex_str)
  match = regex.match version_string

  if match
    major = minor = patch = nil
    special =  = ''

    # Extract out the version parts
    major = match[:major].to_i if match.names.include? 'major'
    minor = match[:minor].to_i if match.names.include? 'minor'
    patch = match[:patch].to_i if match.names.include? 'patch'
    special = match[:special] || '' if match.names.include? 'special'
     = match[:metadata] || '' if match.names.include? 'metadata'

    # Failed parse if major, minor, or patch wasn't found
    # and allow_missing is false
    return nil if !allow_missing and [major, minor, patch].any? {|x| x.nil? }

    # Otherwise, allow them to default to zero
    major ||= 0
    minor ||= 0
    patch ||= 0

    SemVer.new major, minor, patch, special, 
  end
end

.parse_rubygems(version_string) ⇒ Object

Parses a rubygems string, such as ‘v2.0.5.rc.3’ or ‘2.0.5.rc.3’ to ‘v2.0.5-rc.3’



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/xsemver.rb', line 149

def self.parse_rubygems version_string
  if /v?(?<major>\d+)
       (\.(?<minor>\d+)
        (\.(?<patch>\d+)
         (\.(?<pre>[A-Za-z]+\.[0-9A-Za-z]+)
       )?)?)?
      /x =~ version_string

    major = major.to_i
    minor = minor.to_i if minor
    minor ||= 0
    patch = patch.to_i if patch
    patch ||= 0
    pre ||= ''
    SemVer.new major, minor, patch, pre, ''
  else
    SemVer.new
  end
end

Instance Method Details

#<=>(other) ⇒ Object

Compare version numbers according to SemVer 2.0.0-rc2



97
98
99
100
101
102
103
# File 'lib/xsemver.rb', line 97

def <=> other
  [:major, :minor, :patch].each do |method|
    comparison = (send(method) <=> other.send(method))
    return comparison unless comparison == 0
  end
  PreRelease.new(prerelease) <=> PreRelease.new(other.prerelease)
end

#format(fmt) ⇒ Object



83
84
85
86
87
88
89
90
# File 'lib/xsemver.rb', line 83

def format fmt
  fmt = fmt.gsub '%M', @major.to_s
  fmt = fmt.gsub '%m', @minor.to_s
  fmt = fmt.gsub '%p', @patch.to_s
  fmt = fmt.gsub('%s', prerelease? ? "-#{@special}" : '')
  fmt = fmt.gsub('%d', metadata? ? "+#{@metadata}" : '')
  fmt
end

#load(file) ⇒ Object



58
59
60
61
62
63
64
65
66
# File 'lib/xsemver.rb', line 58

def load file
  @file = file
  hash = YAML.load_file(file) || {}
  @major = hash[:major] or raise "invalid semver file: #{file}"
  @minor = hash[:minor] or raise "invalid semver file: #{file}"
  @patch = hash[:patch] or raise "invalid semver file: #{file}"
  @special = hash[:special] or raise "invalid semver file: #{file}"
  @metadata = hash[:metadata] || ""
end

#metadata?Boolean

Return true if the SemVer has a non-empty #metadata value. Otherwise, false.

Returns:

  • (Boolean)


189
190
191
# File 'lib/xsemver.rb', line 189

def metadata?
  !.nil? && .length > 0
end

#prereleaseObject

SemVer specification 2.0.0-rc2 states that anything after the ‘-’ character is prerelease data. To be consistent with the specification verbage, #prerelease returns the same value as #special. TODO: Deprecate #special in favor of #prerelease?



172
173
174
# File 'lib/xsemver.rb', line 172

def prerelease
  special
end

#prerelease=(pre) ⇒ Object

SemVer specification 2.0.0-rc2 states that anything after the ‘-’ character is prerelease data. To be consistent with the specification verbage, #prerelease= sets the same value as #special. TODO: Deprecate #special= in favor of #prerelease=?



179
180
181
# File 'lib/xsemver.rb', line 179

def prerelease=(pre)
  self.special = pre
end

#prerelease?Boolean

Return true if the SemVer has a non-empty #prerelease value. Otherwise, false.

Returns:

  • (Boolean)


184
185
186
# File 'lib/xsemver.rb', line 184

def prerelease?
  !special.nil? && special.length > 0
end

#save(file = nil) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/xsemver.rb', line 68

def save file=nil
  file ||= @file

  hash = {
    :major => @major,
    :minor => @minor,
    :patch => @patch,
    :special => @special,
    :metadata => @metadata
  }

  yaml = YAML.dump hash
  open(file, 'w') { |io| io.write yaml }
end

#to_sObject



92
93
94
# File 'lib/xsemver.rb', line 92

def to_s
  format TAG_FORMAT
end