librarian-puppet 0.9.10 → 0.9.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +82 -19
  3. data/bin/librarian-puppet +0 -2
  4. data/lib/librarian/puppet.rb +32 -4
  5. data/lib/librarian/puppet/cli.rb +7 -0
  6. data/lib/librarian/puppet/dsl.rb +13 -0
  7. data/lib/librarian/puppet/environment.rb +5 -8
  8. data/lib/librarian/puppet/extension.rb +212 -0
  9. data/lib/librarian/puppet/requirement.rb +6 -2
  10. data/lib/librarian/puppet/source.rb +1 -0
  11. data/lib/librarian/puppet/source/forge.rb +62 -35
  12. data/lib/librarian/puppet/source/git.rb +51 -36
  13. data/lib/librarian/puppet/source/githubtarball.rb +44 -28
  14. data/lib/librarian/puppet/source/local.rb +4 -1
  15. data/lib/librarian/puppet/templates/Puppetfile +3 -0
  16. data/lib/librarian/puppet/util.rb +27 -0
  17. data/lib/librarian/puppet/version.rb +1 -1
  18. metadata +106 -207
  19. data/vendor/librarian/CHANGELOG.md +0 -185
  20. data/vendor/librarian/Gemfile +0 -6
  21. data/vendor/librarian/MIT-LICENSE +0 -20
  22. data/vendor/librarian/README.md +0 -403
  23. data/vendor/librarian/Rakefile +0 -34
  24. data/vendor/librarian/bin/librarian-chef +0 -7
  25. data/vendor/librarian/bin/librarian-mock +0 -7
  26. data/vendor/librarian/config/cucumber.yaml +0 -1
  27. data/vendor/librarian/features/chef/cli/init.feature +0 -11
  28. data/vendor/librarian/features/chef/cli/install.feature +0 -64
  29. data/vendor/librarian/features/chef/cli/show.feature +0 -77
  30. data/vendor/librarian/features/chef/cli/version.feature +0 -11
  31. data/vendor/librarian/features/support/env.rb +0 -9
  32. data/vendor/librarian/lib/librarian.rb +0 -19
  33. data/vendor/librarian/lib/librarian/action.rb +0 -5
  34. data/vendor/librarian/lib/librarian/action/base.rb +0 -24
  35. data/vendor/librarian/lib/librarian/action/clean.rb +0 -44
  36. data/vendor/librarian/lib/librarian/action/ensure.rb +0 -24
  37. data/vendor/librarian/lib/librarian/action/install.rb +0 -99
  38. data/vendor/librarian/lib/librarian/action/resolve.rb +0 -81
  39. data/vendor/librarian/lib/librarian/action/update.rb +0 -78
  40. data/vendor/librarian/lib/librarian/chef.rb +0 -1
  41. data/vendor/librarian/lib/librarian/chef/cli.rb +0 -48
  42. data/vendor/librarian/lib/librarian/chef/dsl.rb +0 -15
  43. data/vendor/librarian/lib/librarian/chef/environment.rb +0 -27
  44. data/vendor/librarian/lib/librarian/chef/extension.rb +0 -9
  45. data/vendor/librarian/lib/librarian/chef/integration/knife.rb +0 -42
  46. data/vendor/librarian/lib/librarian/chef/manifest_reader.rb +0 -59
  47. data/vendor/librarian/lib/librarian/chef/source.rb +0 -3
  48. data/vendor/librarian/lib/librarian/chef/source/git.rb +0 -25
  49. data/vendor/librarian/lib/librarian/chef/source/local.rb +0 -69
  50. data/vendor/librarian/lib/librarian/chef/source/path.rb +0 -12
  51. data/vendor/librarian/lib/librarian/chef/source/site.rb +0 -452
  52. data/vendor/librarian/lib/librarian/chef/templates/Cheffile +0 -15
  53. data/vendor/librarian/lib/librarian/cli.rb +0 -205
  54. data/vendor/librarian/lib/librarian/cli/manifest_presenter.rb +0 -79
  55. data/vendor/librarian/lib/librarian/config.rb +0 -7
  56. data/vendor/librarian/lib/librarian/config/database.rb +0 -205
  57. data/vendor/librarian/lib/librarian/config/file_source.rb +0 -47
  58. data/vendor/librarian/lib/librarian/config/hash_source.rb +0 -33
  59. data/vendor/librarian/lib/librarian/config/source.rb +0 -149
  60. data/vendor/librarian/lib/librarian/dependency.rb +0 -91
  61. data/vendor/librarian/lib/librarian/dsl.rb +0 -108
  62. data/vendor/librarian/lib/librarian/dsl/receiver.rb +0 -48
  63. data/vendor/librarian/lib/librarian/dsl/target.rb +0 -172
  64. data/vendor/librarian/lib/librarian/environment.rb +0 -134
  65. data/vendor/librarian/lib/librarian/error.rb +0 -4
  66. data/vendor/librarian/lib/librarian/helpers.rb +0 -13
  67. data/vendor/librarian/lib/librarian/lockfile.rb +0 -29
  68. data/vendor/librarian/lib/librarian/lockfile/compiler.rb +0 -66
  69. data/vendor/librarian/lib/librarian/lockfile/parser.rb +0 -100
  70. data/vendor/librarian/lib/librarian/logger.rb +0 -46
  71. data/vendor/librarian/lib/librarian/manifest.rb +0 -234
  72. data/vendor/librarian/lib/librarian/manifest_set.rb +0 -153
  73. data/vendor/librarian/lib/librarian/mock.rb +0 -1
  74. data/vendor/librarian/lib/librarian/mock/cli.rb +0 -19
  75. data/vendor/librarian/lib/librarian/mock/dsl.rb +0 -15
  76. data/vendor/librarian/lib/librarian/mock/environment.rb +0 -24
  77. data/vendor/librarian/lib/librarian/mock/extension.rb +0 -9
  78. data/vendor/librarian/lib/librarian/mock/source.rb +0 -1
  79. data/vendor/librarian/lib/librarian/mock/source/mock.rb +0 -103
  80. data/vendor/librarian/lib/librarian/mock/source/mock/registry.rb +0 -83
  81. data/vendor/librarian/lib/librarian/resolution.rb +0 -44
  82. data/vendor/librarian/lib/librarian/resolver.rb +0 -78
  83. data/vendor/librarian/lib/librarian/resolver/implementation.rb +0 -118
  84. data/vendor/librarian/lib/librarian/source.rb +0 -2
  85. data/vendor/librarian/lib/librarian/source/git.rb +0 -156
  86. data/vendor/librarian/lib/librarian/source/git/repository.rb +0 -217
  87. data/vendor/librarian/lib/librarian/source/local.rb +0 -61
  88. data/vendor/librarian/lib/librarian/source/path.rb +0 -80
  89. data/vendor/librarian/lib/librarian/spec.rb +0 -13
  90. data/vendor/librarian/lib/librarian/spec_change_set.rb +0 -173
  91. data/vendor/librarian/lib/librarian/specfile.rb +0 -18
  92. data/vendor/librarian/lib/librarian/support/abstract_method.rb +0 -21
  93. data/vendor/librarian/lib/librarian/ui.rb +0 -64
  94. data/vendor/librarian/lib/librarian/version.rb +0 -3
  95. data/vendor/librarian/librarian.gemspec +0 -34
  96. data/vendor/librarian/spec/functional/chef/source/git_spec.rb +0 -432
  97. data/vendor/librarian/spec/functional/chef/source/site_spec.rb +0 -215
  98. data/vendor/librarian/spec/functional/source/git/repository_spec.rb +0 -149
  99. data/vendor/librarian/spec/unit/action/base_spec.rb +0 -18
  100. data/vendor/librarian/spec/unit/action/clean_spec.rb +0 -102
  101. data/vendor/librarian/spec/unit/action/ensure_spec.rb +0 -37
  102. data/vendor/librarian/spec/unit/action/install_spec.rb +0 -111
  103. data/vendor/librarian/spec/unit/config/database_spec.rb +0 -319
  104. data/vendor/librarian/spec/unit/dependency_spec.rb +0 -36
  105. data/vendor/librarian/spec/unit/dsl_spec.rb +0 -194
  106. data/vendor/librarian/spec/unit/environment_spec.rb +0 -9
  107. data/vendor/librarian/spec/unit/lockfile/parser_spec.rb +0 -162
  108. data/vendor/librarian/spec/unit/lockfile_spec.rb +0 -65
  109. data/vendor/librarian/spec/unit/manifest_set_spec.rb +0 -202
  110. data/vendor/librarian/spec/unit/manifest_spec.rb +0 -36
  111. data/vendor/librarian/spec/unit/manifest_version_spec.rb +0 -94
  112. data/vendor/librarian/spec/unit/mock/source/mock_spec.rb +0 -22
  113. data/vendor/librarian/spec/unit/resolver_spec.rb +0 -192
  114. data/vendor/librarian/spec/unit/source/git_spec.rb +0 -29
  115. data/vendor/librarian/spec/unit/spec_change_set_spec.rb +0 -169
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA512:
3
+ data.tar.gz: 26f2450bec2359ed38738c868f21164737d055ee5d8f1eed837fa955dcf6c13ac2e43b71c231a84da5c57c108e371af3f33716929f65ca6a71d66ba0349e87f7
4
+ metadata.gz: 196b417f93a75ce20fe8292826c5cfc3a49d4a9b6ba3e950523575e9e9691ec2339013554fe41a75270a933b6bbdef8446cdba0654991a636c0cbdfa5b64238b
5
+ SHA1:
6
+ data.tar.gz: 03f66d8a1c37f5bcfb97662e532de19e5dc56a4a
7
+ metadata.gz: f43deff66072951260d131337181757ceed57cbd
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Librarian-puppet
2
2
 
3
+ [![Build Status](https://travis-ci.org/rodjek/librarian-puppet.png?branch=master)](https://travis-ci.org/rodjek/librarian-puppet)
4
+
3
5
  ## Introduction
4
6
 
5
7
  Librarian-puppet is a bundler for your puppet infrastructure. You can use
@@ -22,6 +24,15 @@ Every Puppet repository that uses Librarian-puppet will have a file named
22
24
  `Puppetfile` in the root directory of that repository. The full specification
23
25
  for which modules your puppet infrastructure repository depends goes in here.
24
26
 
27
+ ### Simple Puppetfile
28
+
29
+ This Puppetfile will download all the dependencies listed in your Modulefile from the Puppet Forge
30
+
31
+ forge "http://forge.puppetlabs.com"
32
+
33
+ modulefile
34
+
35
+
25
36
  ### Example Puppetfile
26
37
 
27
38
  forge "http://forge.puppetlabs.com"
@@ -38,6 +49,11 @@ for which modules your puppet infrastructure repository depends goes in here.
38
49
  *See [jenkins-appliance](https://github.com/aussielunix/jenkins-appliance) for
39
50
  a puppet repo already setup to use librarian-puppet.*
40
51
 
52
+ ### Recursive module dependency resolving
53
+
54
+ When fetching a module from a `:git`-source all dependencies specified in its
55
+ `Modulefile` and `Puppetfile` will be resolved and installed.
56
+
41
57
  ### Puppetfile Breakdown
42
58
 
43
59
  forge "http://forge.puppetlabs.com"
@@ -146,6 +162,72 @@ Update the version of a dependency:
146
162
  $ git add Puppetfile.lock
147
163
  $ git commit -m "bumped the version of apt up to 0.0.4."
148
164
 
165
+ ## Configuration
166
+
167
+ Configuration comes from three sources with the following highest-to-lowest
168
+ precedence:
169
+
170
+ * The local config (`./.librarian/puppet/config`)
171
+ * The environment
172
+ * The global config (`~/.librarian/puppet/config`)
173
+
174
+ You can inspect the final configuration with:
175
+
176
+ $ librarian-puppet config
177
+
178
+ You can find out where a particular key is set with:
179
+
180
+ $ librarian-puppet config KEY
181
+
182
+ You can set a key at the global level with:
183
+
184
+ $ librarian-puppet config KEY VALUE --global
185
+
186
+ And remove it with:
187
+
188
+ $ librarian-puppet config KEY --global --delete
189
+
190
+ You can set a key at the local level with:
191
+
192
+ $ librarian-puppet config KEY VALUE --local
193
+
194
+ And remove it with:
195
+
196
+ $ librarian-puppet config KEY --local --delete
197
+
198
+ You cannot set or delete environment-level config keys with the CLI.
199
+
200
+ Configuration set at either the global or local level will affect subsequent
201
+ invocations of `librarian-puppet`. Configurations set at the environment level are
202
+ not saved and will not affect subsequent invocations of `librarian-puppet`.
203
+
204
+ You can pass a config at the environment level by taking the original config key
205
+ and transforming it: replace hyphens (`-`) with underscores (`_`) and periods
206
+ (`.`) with doubled underscores (`__`), uppercase, and finally prefix with
207
+ `LIBRARIAN_PUPPET_`. For example, to pass a config in the environment for the key
208
+ `part-one.part-two`, set the environment variable
209
+ `LIBRARIAN_PUPPET_PART_ONE__PART_TWO`.
210
+
211
+ Configuration affects how various commands operate.
212
+
213
+ * The `path` config sets the cookbooks directory to install to. If a relative
214
+ path, it is relative to the directory containing the `Puppetfile`. The
215
+ equivalent environment variable is `LIBRARIAN_PUPPET_PATH`.
216
+
217
+ * The `tmp` config sets the cache directory for librarian. If a relative
218
+ path, it is relative to the directory containing the `Puppetfile`. The
219
+ equivalent environment variable is `LIBRARIAN_PUPPET_TMP`.
220
+
221
+ Configuration can be set by passing specific options to other commands.
222
+
223
+ * The `path` config can be set at the local level by passing the `--path` option
224
+ to the `install` command. It can be unset at the local level by passing the
225
+ `--no-path` option to the `install` command. Note that if this is set at the
226
+ environment or global level then, even if `--no-path` is given as an option,
227
+ the environment or global config will be used.
228
+
229
+
230
+
149
231
  ## How to Contribute
150
232
 
151
233
  * Pull requests please.
@@ -162,25 +244,6 @@ Please include:
162
244
  * Please run the `librarian-puppet` commands in verbose mode by using the
163
245
  `--verbose` flag, and include the verbose output in the bug report as well.
164
246
 
165
- ## Changelog
166
-
167
- ### 0.9.0
168
-
169
- * Initial release
170
-
171
- ### 0.9.1
172
-
173
- * Proper error message when a module that is sourced from the forge does not
174
- exist.
175
- * Added support for annotated tags as git references.
176
- * `librarian-puppet init` adds `.tmp/` to gitignore instead of `tmp/`.
177
- * Fixed syntax error in the template Puppetfile created by `librarian-puppet
178
- init`.
179
- * Checks for `lib/puppet` as well as `manifests/` when checking if the git
180
- repository is a valid module.
181
- * When a user specifies `<foo>/<bar>` as the name of a module sources from a
182
- git repository, assume the module name is actually `<bar>`.
183
- * Fixed gem description and summary in gemspec.
184
247
 
185
248
  ## License
186
249
  Please see the [LICENSE](https://github.com/rodjek/librarian-puppet/blob/master/LICENSE)
@@ -1,9 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  lib = File.expand_path('../../lib', __FILE__)
4
- vendor = File.expand_path('../../vendor/librarian/lib', __FILE__)
5
4
  $:.unshift(lib) unless $:.include?(lib)
6
- $:.unshift(vendor) unless $:.include?(vendor)
7
5
 
8
6
  require 'librarian/puppet/cli'
9
7
  Librarian::Puppet::Cli.bin!
@@ -1,16 +1,44 @@
1
1
  require 'librarian'
2
2
  require 'fileutils'
3
+ require 'open3'
4
+
5
+ # require open3_backport in ruby 1.8 and install if not present
6
+ # https://github.com/rodjek/librarian-puppet/issues/167
7
+ if RUBY_VERSION < '1.9'
8
+ begin
9
+ require 'open3_backport'
10
+ rescue LoadError
11
+ require 'rubygems/dependency_installer.rb'
12
+ Gem::DependencyInstaller.new.install 'open3_backport'
13
+ require 'open3_backport'
14
+ end
15
+ end
16
+
17
+ status = nil
18
+ out = nil
19
+ error = nil
3
20
 
4
21
  begin
5
- require 'puppet'
6
- rescue LoadError
22
+ Open3.popen3('puppet --version') {|stdin, stdout, stderr, wait_thr|
23
+ pid = wait_thr.pid # pid of the started process.
24
+ out = stdout.read
25
+ status = wait_thr.value # Process::Status object returned.
26
+ }
27
+ rescue => e
28
+ error = e
29
+ end
30
+
31
+ if status.nil? or status.exitstatus != 0
7
32
  $stderr.puts <<-EOF
8
- Unable to load puppet. Either install it using native packages for your
9
- platform (eg .deb, .rpm, .dmg, etc) or as a gem (gem install puppet).
33
+ Unable to load puppet. Please install it using native packages for your platform (eg .deb, .rpm, .dmg, etc).
34
+ #{out.nil? or out.empty? ? "puppet --version returned #{status.exitstatus}" : out}
35
+ #{error.message unless error.nil?}
10
36
  EOF
11
37
  exit 1
12
38
  end
13
39
 
40
+ PUPPET_VERSION=out.split(' ').first.strip
41
+
14
42
  require 'librarian/puppet/extension'
15
43
  require 'librarian/puppet/version'
16
44
 
@@ -45,6 +45,12 @@ module Librarian
45
45
  option "destructive", :type => :boolean, :default => false
46
46
  option "local", :type => :boolean, :default => false
47
47
  def install
48
+
49
+ unless File.exist?('Puppetfile')
50
+ say "Could not find Puppetfile in #{Dir.pwd}", :red
51
+ exit 1
52
+ end
53
+
48
54
  ensure!
49
55
  clean! if options["clean"]
50
56
  unless options["destructive"].nil?
@@ -61,6 +67,7 @@ module Librarian
61
67
  environment.config_db.local['mode'] = options['local'] ? 'local' : nil
62
68
 
63
69
  resolve!
70
+ debug { "Install: dependencies resolved"}
64
71
  install!
65
72
  end
66
73
 
@@ -14,3 +14,16 @@ module Librarian
14
14
  end
15
15
  end
16
16
  end
17
+
18
+ module Librarian
19
+ class Dsl
20
+ class Receiver
21
+ def modulefile
22
+ File.read('Modulefile').lines.each do |line|
23
+ regexp = /\s*dependency\s+('|")([^'"]+)\1\s*(?:,\s*('|")([^'"]+)\3)?/
24
+ regexp =~ line && mod($2, $4)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -11,6 +11,11 @@ module Librarian
11
11
  "puppet"
12
12
  end
13
13
 
14
+ def tmp_path
15
+ part = config_db["tmp"] || ".tmp"
16
+ project_path.join(part)
17
+ end
18
+
14
19
  def install_path
15
20
  part = config_db["path"] || "modules"
16
21
  project_path.join(part)
@@ -28,14 +33,6 @@ module Librarian
28
33
  vendor_path.join('source')
29
34
  end
30
35
 
31
- def cache_path
32
- project_path.join(".tmp/librarian/cache")
33
- end
34
-
35
- def scratch_path
36
- project_path.join(".tmp/librarian/scratch")
37
- end
38
-
39
36
  def vendor!
40
37
  vendor_cache.mkpath unless vendor_cache.exist?
41
38
  vendor_source.mkpath unless vendor_source.exist?
@@ -1,9 +1,221 @@
1
1
  require 'librarian/puppet/environment'
2
+ require 'librarian/action/base'
2
3
 
3
4
  module Librarian
4
5
  module Puppet
5
6
  extend self
6
7
  extend Librarian
8
+ end
9
+
10
+ class Dependency
11
+ class Requirement
12
+ def initialize(*args)
13
+ args = initialize_normalize_args(args)
14
+ self.backing = Gem::Requirement.create(puppet_to_gem_versions(args))
15
+ end
16
+
17
+ def puppet_to_gem_versions(args)
18
+ args.map do |arg|
19
+ case arg
20
+ when Array
21
+ arg.map { |v| Librarian::Puppet::Requirement.new(v).gem_requirement }
22
+ when String
23
+ Librarian::Puppet::Requirement.new(arg).gem_requirement
24
+ else
25
+ # Gem::Requirement, convert to string (ie. =1.0) so we can concat later
26
+ # Gem::Requirements can not be concatenated
27
+ arg.requirements.map{|x,y| "#{x}#{y}"}
28
+ end
29
+ end.flatten
30
+ end
31
+ end
32
+
33
+ alias :eql? :==
34
+
35
+ def hash
36
+ self.to_s.hash
37
+ end
38
+ end
39
+
40
+ # Fixes for librarian not yet released in their gem
41
+ module Mock
42
+ module Source
43
+ class Mock
44
+ alias :eql? :==
45
+
46
+ def hash
47
+ self.to_s.hash
48
+ end
49
+ end
50
+ end
51
+ end
52
+ module Source
53
+ class Git
54
+ alias :eql? :==
55
+
56
+ def hash
57
+ self.to_s.hash
58
+ end
59
+ end
60
+
61
+ class Path
62
+ alias :eql? :==
63
+
64
+ def hash
65
+ self.to_s.hash
66
+ end
67
+ end
68
+ end
69
+
70
+ module Action
71
+ class Install < Base
72
+
73
+ private
74
+
75
+ def create_install_path
76
+ install_path.rmtree if install_path.exist? && destructive?
77
+ install_path.mkpath
78
+ end
79
+
80
+ def destructive?
81
+ environment.config_db.local['destructive'] == 'true'
82
+ end
83
+ end
84
+ end
85
+
86
+ class ManifestSet
87
+ private
7
88
 
89
+ # Check if module doesn't exist and fail fast
90
+ def dependencies_of(names)
91
+ names = Array === names ? names.dup : names.to_a
92
+ assert_strings!(names)
93
+
94
+ deps = Set.new
95
+ until names.empty?
96
+ name = names.shift
97
+ next if deps.include?(name)
98
+
99
+ deps << name
100
+ raise(Error, "Unable to find module #{name}") if index[name].nil?
101
+ names.concat index[name].dependencies.map(&:name)
102
+ end
103
+ deps.to_a
104
+ end
8
105
  end
106
+
107
+ class Manifest
108
+
109
+ class PreReleaseVersion
110
+
111
+ # Compares pre-release component ids using Semver 2.0.0 spec
112
+ def self.compare_components(this_id,other_id)
113
+ case # Strings have higher precedence than numbers
114
+ when (this_id.is_a?(Integer) and other_id.is_a?(String))
115
+ -1
116
+ when (this_id.is_a?(String) and other_id.is_a?(Integer))
117
+ 1
118
+ else
119
+ this_id <=> other_id
120
+ end
121
+ end
122
+
123
+ # Parses pre-release components `a.b.c` into an array ``[a,b,c]`
124
+ # Converts numeric components into +Integer+
125
+ def self.parse(prerelease)
126
+ if prerelease.nil?
127
+ []
128
+ else
129
+ prerelease.split('.').collect do |id|
130
+ id = Integer(id) if /^[0-9]+$/ =~ id
131
+ id
132
+ end
133
+ end
134
+ end
135
+
136
+ include Comparable
137
+
138
+ attr_reader :components
139
+
140
+ def initialize(prerelease)
141
+ @prerelease = prerelease
142
+ @components = PreReleaseVersion.parse(prerelease)
143
+ end
144
+
145
+ def to_s
146
+ @prerelease
147
+ end
148
+
149
+ def <=>(other)
150
+ # null-fill zip array to prevent loss of components
151
+ z = Array.new([components.length,other.components.length])
152
+
153
+ # Compare each component against the other
154
+ comp = z.zip(components,other.components).collect do |ids|
155
+ case # All components being equal, the version with more of them takes precedence
156
+ when ids[1].nil? # Self has less elements, other wins
157
+ -1
158
+ when ids[2].nil? # Other has less elements, self wins
159
+ 1
160
+ else
161
+ PreReleaseVersion.compare_components(ids[1],ids[2])
162
+ end
163
+ end
164
+ # Chose the first non-zero comparison or return 0
165
+ comp.delete_if {|c| c == 0}[0] || 0
166
+ end
167
+ end
168
+ class Version
169
+ @@SEMANTIC_VERSION_PATTERN = /^([0-9]+\.[0-9]+(?:\.[0-9]+)?)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/
170
+ def self.parse_semver(version_string)
171
+ parsed = @@SEMANTIC_VERSION_PATTERN.match(version_string.strip)
172
+ if parsed
173
+ {
174
+ :full_version => parsed[0],
175
+ :version => parsed[1],
176
+ :prerelease => (PreReleaseVersion.new(parsed[2]) if parsed[2]),
177
+ :build => parsed[3]
178
+ }
179
+ end
180
+ end
181
+
182
+ attr_reader :prerelease
183
+
184
+ def initialize(*args)
185
+ args = initialize_normalize_args(args)
186
+ semver = Version.parse_semver(*args)
187
+ if semver
188
+ self.backing = Gem::Version.new(semver[:version])
189
+ @prerelease = semver[:prerelease]
190
+ @full_version = semver[:full_version]
191
+ else
192
+ self.backing = Gem::Version.new(*args)
193
+ @full_version = to_gem_version.to_s
194
+ end
195
+ end
196
+
197
+ def <=>(other)
198
+ cmp = to_gem_version <=> other.to_gem_version
199
+
200
+ # Should compare pre-release versions?
201
+ if cmp == 0 and not (prerelease.nil? and other.prerelease.nil?)
202
+ case # Versions without prerelease take precedence
203
+ when (prerelease.nil? and not other.prerelease.nil?)
204
+ 1
205
+ when (not prerelease.nil? and other.prerelease.nil?)
206
+ -1
207
+ else
208
+ prerelease <=> other.prerelease
209
+ end
210
+ else
211
+ cmp
212
+ end
213
+ end
214
+
215
+ def to_s
216
+ @full_version
217
+ end
218
+ end
219
+ end
220
+
9
221
  end