gel 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -0
- data/exe/gel +13 -0
- data/lib/gel.rb +22 -0
- data/lib/gel/catalog.rb +153 -0
- data/lib/gel/catalog/common.rb +82 -0
- data/lib/gel/catalog/compact_index.rb +152 -0
- data/lib/gel/catalog/dependency_index.rb +125 -0
- data/lib/gel/catalog/legacy_index.rb +157 -0
- data/lib/gel/catalog/marshal_hacks.rb +16 -0
- data/lib/gel/command.rb +86 -0
- data/lib/gel/command/config.rb +11 -0
- data/lib/gel/command/env.rb +7 -0
- data/lib/gel/command/exec.rb +66 -0
- data/lib/gel/command/help.rb +7 -0
- data/lib/gel/command/install.rb +7 -0
- data/lib/gel/command/install_gem.rb +16 -0
- data/lib/gel/command/lock.rb +34 -0
- data/lib/gel/command/ruby.rb +10 -0
- data/lib/gel/command/shell_setup.rb +25 -0
- data/lib/gel/command/stub.rb +12 -0
- data/lib/gel/command/update.rb +11 -0
- data/lib/gel/compatibility.rb +4 -0
- data/lib/gel/compatibility/bundler.rb +54 -0
- data/lib/gel/compatibility/bundler/cli.rb +6 -0
- data/lib/gel/compatibility/bundler/friendly_errors.rb +3 -0
- data/lib/gel/compatibility/bundler/setup.rb +4 -0
- data/lib/gel/compatibility/rubygems.rb +192 -0
- data/lib/gel/compatibility/rubygems/command.rb +4 -0
- data/lib/gel/compatibility/rubygems/dependency_installer.rb +0 -0
- data/lib/gel/compatibility/rubygems/gem_runner.rb +6 -0
- data/lib/gel/config.rb +80 -0
- data/lib/gel/db.rb +294 -0
- data/lib/gel/direct_gem.rb +29 -0
- data/lib/gel/environment.rb +592 -0
- data/lib/gel/error.rb +104 -0
- data/lib/gel/gemfile_parser.rb +144 -0
- data/lib/gel/gemspec_parser.rb +95 -0
- data/lib/gel/git_catalog.rb +38 -0
- data/lib/gel/git_depot.rb +119 -0
- data/lib/gel/httpool.rb +148 -0
- data/lib/gel/installer.rb +251 -0
- data/lib/gel/lock_loader.rb +164 -0
- data/lib/gel/lock_parser.rb +64 -0
- data/lib/gel/locked_store.rb +126 -0
- data/lib/gel/multi_store.rb +96 -0
- data/lib/gel/package.rb +156 -0
- data/lib/gel/package/inspector.rb +23 -0
- data/lib/gel/package/installer.rb +267 -0
- data/lib/gel/path_catalog.rb +44 -0
- data/lib/gel/pinboard.rb +140 -0
- data/lib/gel/pub_grub/preference_strategy.rb +82 -0
- data/lib/gel/pub_grub/source.rb +153 -0
- data/lib/gel/runtime.rb +27 -0
- data/lib/gel/store.rb +205 -0
- data/lib/gel/store_catalog.rb +31 -0
- data/lib/gel/store_gem.rb +80 -0
- data/lib/gel/stub_set.rb +51 -0
- data/lib/gel/support/gem_platform.rb +225 -0
- data/lib/gel/support/gem_requirement.rb +264 -0
- data/lib/gel/support/gem_version.rb +398 -0
- data/lib/gel/support/tar.rb +13 -0
- data/lib/gel/support/tar/tar_header.rb +229 -0
- data/lib/gel/support/tar/tar_reader.rb +123 -0
- data/lib/gel/support/tar/tar_reader/entry.rb +154 -0
- data/lib/gel/support/tar/tar_writer.rb +339 -0
- data/lib/gel/tail_file.rb +205 -0
- data/lib/gel/version.rb +5 -0
- data/lib/gel/work_pool.rb +143 -0
- data/man/man1/gel-exec.1 +16 -0
- data/man/man1/gel-install.1 +16 -0
- data/man/man1/gel.1 +30 -0
- metadata +131 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Gel::StoreCatalog
|
4
|
+
attr_reader :store
|
5
|
+
|
6
|
+
def initialize(store)
|
7
|
+
@store = store
|
8
|
+
@cache = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def gem_info(name)
|
12
|
+
@cache.fetch(name) { @cache[name] = _info(name) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def _info(name)
|
16
|
+
info = {}
|
17
|
+
|
18
|
+
@store.each(name) do |store_gem|
|
19
|
+
info[store_gem.version] = {
|
20
|
+
dependencies: store_gem.dependencies.map do |name, pairs|
|
21
|
+
[name, pairs.map { |op, ver| "#{op} #{ver}" }]
|
22
|
+
end,
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
info
|
27
|
+
end
|
28
|
+
|
29
|
+
def prepare
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Gel::StoreGem
|
4
|
+
EXTENSION_SUBDIR_TOKEN = ".."
|
5
|
+
|
6
|
+
attr_reader :root, :name, :version, :extensions, :info
|
7
|
+
|
8
|
+
def initialize(root, name, version, extensions, info)
|
9
|
+
@root = root
|
10
|
+
@name = name
|
11
|
+
@version = version
|
12
|
+
@extensions = extensions unless extensions && extensions.empty?
|
13
|
+
@info = info
|
14
|
+
end
|
15
|
+
|
16
|
+
def ==(other)
|
17
|
+
other.class == self.class && @name == other.name && @version == other.version
|
18
|
+
end
|
19
|
+
|
20
|
+
def hash
|
21
|
+
@name.hash ^ @version.hash
|
22
|
+
end
|
23
|
+
|
24
|
+
def satisfies?(requirements)
|
25
|
+
requirements.satisfied_by?(gem_version)
|
26
|
+
end
|
27
|
+
|
28
|
+
def require_paths
|
29
|
+
paths = _require_paths.map { |reqp| "#{root}/#{reqp}" }
|
30
|
+
paths << extensions if extensions
|
31
|
+
raise(paths.inspect) unless paths.all? { |path| path.is_a?(String) }
|
32
|
+
paths
|
33
|
+
end
|
34
|
+
|
35
|
+
def bindir
|
36
|
+
@info[:bindir] || "bin"
|
37
|
+
end
|
38
|
+
|
39
|
+
def dependencies
|
40
|
+
@info[:dependencies]
|
41
|
+
end
|
42
|
+
|
43
|
+
def executables
|
44
|
+
@info[:executables]
|
45
|
+
end
|
46
|
+
|
47
|
+
def path(file, subdir = nil)
|
48
|
+
if subdir == EXTENSION_SUBDIR_TOKEN && extensions
|
49
|
+
"#{extensions}/#{file}"
|
50
|
+
else
|
51
|
+
subdir ||= _default_require_path
|
52
|
+
"#{root}/#{subdir}/#{file}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def libs
|
57
|
+
_require_paths.each do |subdir|
|
58
|
+
prefix = "#{root}/#{subdir}/"
|
59
|
+
Dir["#{prefix}**/*.rb"].each do |path|
|
60
|
+
next unless path.start_with?(prefix)
|
61
|
+
file = path[prefix.size..-1].sub(/\.rb$/, "")
|
62
|
+
yield file, subdir
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def gem_version
|
70
|
+
@gem_version ||= Gel::Support::GemVersion.new(version)
|
71
|
+
end
|
72
|
+
|
73
|
+
def _require_paths
|
74
|
+
@info[:require_paths]
|
75
|
+
end
|
76
|
+
|
77
|
+
def _default_require_path
|
78
|
+
_require_paths.first
|
79
|
+
end
|
80
|
+
end
|
data/lib/gel/stub_set.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "db"
|
4
|
+
|
5
|
+
class Gel::StubSet
|
6
|
+
attr_reader :root
|
7
|
+
|
8
|
+
def initialize(root)
|
9
|
+
@root = File.realpath(File.expand_path(root))
|
10
|
+
@db = Gel::DB.new(root, "stubs")
|
11
|
+
@dir = File.join(@root, "bin")
|
12
|
+
end
|
13
|
+
|
14
|
+
def add(store, executables)
|
15
|
+
@db.writing do
|
16
|
+
executables.each do |exe|
|
17
|
+
create_stub(exe) unless File.exist?(bin(exe))
|
18
|
+
@db[exe] = (@db[exe] || []) + [store]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def remove(store, executables)
|
24
|
+
@db.writing do
|
25
|
+
executables.each do |exe|
|
26
|
+
remaining_stores = (@db[exe] || []) - [store]
|
27
|
+
if remaining_stores.empty?
|
28
|
+
File.unlink(bin(exe))
|
29
|
+
@db.delete(exe)
|
30
|
+
else
|
31
|
+
@db[exe] = remaining_stores
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def create_stub(exe)
|
38
|
+
Dir.mkdir(@dir) unless Dir.exist?(@dir)
|
39
|
+
|
40
|
+
File.open(bin(exe), "w", 0755) do |f|
|
41
|
+
f.write(<<STUB)
|
42
|
+
#!/usr/bin/env gel stub #{exe}
|
43
|
+
# This file is generated and managed by Gel.
|
44
|
+
STUB
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def bin(exe)
|
49
|
+
File.join(@dir, exe)
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,225 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# Copyright (c) Chad Fowler, Rich Kilmer, Jim Weirich and others.
|
4
|
+
# Portions copyright (c) Engine Yard and Andre Arko
|
5
|
+
#
|
6
|
+
# Redistributed under the terms of the MIT license
|
7
|
+
#
|
8
|
+
|
9
|
+
require "rubygems/deprecate"
|
10
|
+
|
11
|
+
##
|
12
|
+
# Available list of platforms for targeting Gem installations.
|
13
|
+
#
|
14
|
+
# See `gem help platform` for information on platform matching.
|
15
|
+
|
16
|
+
class Gel::Support::GemPlatform
|
17
|
+
|
18
|
+
@local = nil
|
19
|
+
|
20
|
+
attr_accessor :cpu
|
21
|
+
|
22
|
+
attr_accessor :os
|
23
|
+
|
24
|
+
attr_accessor :version
|
25
|
+
|
26
|
+
def self.local
|
27
|
+
arch = RbConfig::CONFIG['arch']
|
28
|
+
arch = "#{arch}_60" if arch =~ /mswin(?:32|64)$/
|
29
|
+
@local ||= new(arch)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.platforms=(platforms)
|
33
|
+
@platforms = platforms
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.platforms
|
37
|
+
@platforms ||= []
|
38
|
+
if @platforms.empty?
|
39
|
+
@platforms = [Gel::Support::GemPlatform::RUBY, Gel::Support::GemPlatform.local]
|
40
|
+
end
|
41
|
+
@platforms
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.match(platform)
|
45
|
+
platforms.any? do |local_platform|
|
46
|
+
platform.nil? or
|
47
|
+
local_platform == platform or
|
48
|
+
(local_platform != Gel::Support::GemPlatform::RUBY and local_platform =~ platform)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.installable?(spec)
|
53
|
+
if spec.respond_to? :installable_platform?
|
54
|
+
spec.installable_platform?
|
55
|
+
else
|
56
|
+
match spec.platform
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.new(arch) # :nodoc:
|
61
|
+
case arch
|
62
|
+
when Gel::Support::GemPlatform::CURRENT then
|
63
|
+
Gel::Support::GemPlatform.local
|
64
|
+
when Gel::Support::GemPlatform::RUBY, nil, '' then
|
65
|
+
Gel::Support::GemPlatform::RUBY
|
66
|
+
else
|
67
|
+
super
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def initialize(arch)
|
72
|
+
case arch
|
73
|
+
when Array then
|
74
|
+
@cpu, @os, @version = arch
|
75
|
+
when String then
|
76
|
+
arch = arch.split '-'
|
77
|
+
|
78
|
+
if arch.length > 2 and arch.last !~ /\d/ # reassemble x86-linux-gnu
|
79
|
+
extra = arch.pop
|
80
|
+
arch.last << "-#{extra}"
|
81
|
+
end
|
82
|
+
|
83
|
+
cpu = arch.shift
|
84
|
+
|
85
|
+
@cpu = case cpu
|
86
|
+
when /i\d86/ then 'x86'
|
87
|
+
else cpu
|
88
|
+
end
|
89
|
+
|
90
|
+
if arch.length == 2 and arch.last =~ /^\d+(\.\d+)?$/ # for command-line
|
91
|
+
@os, @version = arch
|
92
|
+
return
|
93
|
+
end
|
94
|
+
|
95
|
+
os, = arch
|
96
|
+
@cpu, os = nil, cpu if os.nil? # legacy jruby
|
97
|
+
|
98
|
+
@os, @version = case os
|
99
|
+
when /aix(\d+)?/ then [ 'aix', $1 ]
|
100
|
+
when /cygwin/ then [ 'cygwin', nil ]
|
101
|
+
when /darwin(\d+)?/ then [ 'darwin', $1 ]
|
102
|
+
when /^macruby$/ then [ 'macruby', nil ]
|
103
|
+
when /freebsd(\d+)?/ then [ 'freebsd', $1 ]
|
104
|
+
when /hpux(\d+)?/ then [ 'hpux', $1 ]
|
105
|
+
when /^java$/, /^jruby$/ then [ 'java', nil ]
|
106
|
+
when /^java([\d.]*)/ then [ 'java', $1 ]
|
107
|
+
when /^dalvik(\d+)?$/ then [ 'dalvik', $1 ]
|
108
|
+
when /^dotnet$/ then [ 'dotnet', nil ]
|
109
|
+
when /^dotnet([\d.]*)/ then [ 'dotnet', $1 ]
|
110
|
+
when /linux/ then [ 'linux', $1 ]
|
111
|
+
when /mingw32/ then [ 'mingw32', nil ]
|
112
|
+
when /(mswin\d+)(\_(\d+))?/ then
|
113
|
+
os, version = $1, $3
|
114
|
+
@cpu = 'x86' if @cpu.nil? and os =~ /32$/
|
115
|
+
[os, version]
|
116
|
+
when /netbsdelf/ then [ 'netbsdelf', nil ]
|
117
|
+
when /openbsd(\d+\.\d+)?/ then [ 'openbsd', $1 ]
|
118
|
+
when /bitrig(\d+\.\d+)?/ then [ 'bitrig', $1 ]
|
119
|
+
when /solaris(\d+\.\d+)?/ then [ 'solaris', $1 ]
|
120
|
+
# test
|
121
|
+
when /^(\w+_platform)(\d+)?/ then [ $1, $2 ]
|
122
|
+
else [ 'unknown', nil ]
|
123
|
+
end
|
124
|
+
when Gel::Support::GemPlatform then
|
125
|
+
@cpu = arch.cpu
|
126
|
+
@os = arch.os
|
127
|
+
@version = arch.version
|
128
|
+
else
|
129
|
+
raise ArgumentError, "invalid argument #{arch.inspect}"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def inspect
|
134
|
+
"%s @cpu=%p, @os=%p, @version=%p>" % [super[0..-2], *to_a]
|
135
|
+
end
|
136
|
+
|
137
|
+
def to_a
|
138
|
+
[@cpu, @os, @version]
|
139
|
+
end
|
140
|
+
|
141
|
+
def to_s
|
142
|
+
to_a.compact.join '-'
|
143
|
+
end
|
144
|
+
|
145
|
+
##
|
146
|
+
# Is +other+ equal to this platform? Two platforms are equal if they have
|
147
|
+
# the same CPU, OS and version.
|
148
|
+
|
149
|
+
def ==(other)
|
150
|
+
self.class === other and to_a == other.to_a
|
151
|
+
end
|
152
|
+
|
153
|
+
alias :eql? :==
|
154
|
+
|
155
|
+
def hash # :nodoc:
|
156
|
+
to_a.hash
|
157
|
+
end
|
158
|
+
|
159
|
+
##
|
160
|
+
# Does +other+ match this platform? Two platforms match if they have the
|
161
|
+
# same CPU, or either has a CPU of 'universal', they have the same OS, and
|
162
|
+
# they have the same version, or either has no version.
|
163
|
+
#
|
164
|
+
# Additionally, the platform will match if the local CPU is 'arm' and the
|
165
|
+
# other CPU starts with "arm" (for generic ARM family support).
|
166
|
+
|
167
|
+
def ===(other)
|
168
|
+
return nil unless Gel::Support::GemPlatform === other
|
169
|
+
|
170
|
+
# cpu
|
171
|
+
([nil,'universal'].include?(@cpu) or [nil, 'universal'].include?(other.cpu) or @cpu == other.cpu or
|
172
|
+
(@cpu == 'arm' and other.cpu =~ /\Aarm/)) and
|
173
|
+
|
174
|
+
# os
|
175
|
+
@os == other.os and
|
176
|
+
|
177
|
+
# version
|
178
|
+
(@version.nil? or other.version.nil? or @version == other.version)
|
179
|
+
end
|
180
|
+
|
181
|
+
##
|
182
|
+
# Does +other+ match this platform? If +other+ is a String it will be
|
183
|
+
# converted to a Gel::Support::GemPlatform first. See #=== for matching rules.
|
184
|
+
|
185
|
+
def =~(other)
|
186
|
+
case other
|
187
|
+
when Gel::Support::GemPlatform then # nop
|
188
|
+
when String then
|
189
|
+
# This data is from http://gems.rubyforge.org/gems/yaml on 19 Aug 2007
|
190
|
+
other = case other
|
191
|
+
when /^i686-darwin(\d)/ then ['x86', 'darwin', $1 ]
|
192
|
+
when /^i\d86-linux/ then ['x86', 'linux', nil ]
|
193
|
+
when 'java', 'jruby' then [nil, 'java', nil ]
|
194
|
+
when /^dalvik(\d+)?$/ then [nil, 'dalvik', $1 ]
|
195
|
+
when /dotnet(\-(\d+\.\d+))?/ then ['universal','dotnet', $2 ]
|
196
|
+
when /mswin32(\_(\d+))?/ then ['x86', 'mswin32', $2 ]
|
197
|
+
when /mswin64(\_(\d+))?/ then ['x64', 'mswin64', $2 ]
|
198
|
+
when 'powerpc-darwin' then ['powerpc', 'darwin', nil ]
|
199
|
+
when /powerpc-darwin(\d)/ then ['powerpc', 'darwin', $1 ]
|
200
|
+
when /sparc-solaris2.8/ then ['sparc', 'solaris', '2.8' ]
|
201
|
+
when /universal-darwin(\d)/ then ['universal', 'darwin', $1 ]
|
202
|
+
else other
|
203
|
+
end
|
204
|
+
|
205
|
+
other = Gel::Support::GemPlatform.new other
|
206
|
+
else
|
207
|
+
return nil
|
208
|
+
end
|
209
|
+
|
210
|
+
self === other
|
211
|
+
end
|
212
|
+
|
213
|
+
##
|
214
|
+
# A pure-Ruby gem that may use Gem::Specification#extensions to build
|
215
|
+
# binary files.
|
216
|
+
|
217
|
+
RUBY = 'ruby'.freeze
|
218
|
+
|
219
|
+
##
|
220
|
+
# A platform-specific gem that is built for the packaging Ruby's platform.
|
221
|
+
# This will be replaced with Gel::Support::GemPlatform::local.
|
222
|
+
|
223
|
+
CURRENT = 'current'.freeze
|
224
|
+
|
225
|
+
end
|
@@ -0,0 +1,264 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# Copyright (c) Chad Fowler, Rich Kilmer, Jim Weirich and others.
|
4
|
+
# Portions copyright (c) Engine Yard and Andre Arko
|
5
|
+
#
|
6
|
+
# Redistributed under the terms of the MIT license
|
7
|
+
#
|
8
|
+
|
9
|
+
require_relative "gem_version"
|
10
|
+
|
11
|
+
##
|
12
|
+
# A Requirement is a set of one or more version restrictions. It supports a
|
13
|
+
# few (<tt>=, !=, >, <, >=, <=, ~></tt>) different restriction operators.
|
14
|
+
#
|
15
|
+
# See Gem::Version for a description on how versions and requirements work
|
16
|
+
# together in RubyGems.
|
17
|
+
|
18
|
+
class Gel::Support::GemRequirement
|
19
|
+
OPS = { #:nodoc:
|
20
|
+
"=" => lambda { |v, r| v == r },
|
21
|
+
"!=" => lambda { |v, r| v != r },
|
22
|
+
">" => lambda { |v, r| v > r },
|
23
|
+
"<" => lambda { |v, r| v < r },
|
24
|
+
">=" => lambda { |v, r| v >= r },
|
25
|
+
"<=" => lambda { |v, r| v <= r },
|
26
|
+
"~>" => lambda { |v, r| v >= r && v.release < r.bump }
|
27
|
+
}
|
28
|
+
|
29
|
+
SOURCE_SET_REQUIREMENT = Struct.new(:for_lockfile).new "!" # :nodoc:
|
30
|
+
|
31
|
+
quoted = OPS.keys.map { |k| Regexp.quote k }.join "|"
|
32
|
+
PATTERN_RAW = "\\s*(#{quoted})?\\s*(#{Gel::Support::GemVersion::VERSION_PATTERN})\\s*" # :nodoc:
|
33
|
+
|
34
|
+
##
|
35
|
+
# A regular expression that matches a requirement
|
36
|
+
|
37
|
+
PATTERN = /\A#{PATTERN_RAW}\z/
|
38
|
+
|
39
|
+
##
|
40
|
+
# The default requirement matches any version
|
41
|
+
|
42
|
+
DefaultRequirement = [">=", Gel::Support::GemVersion.new(0)]
|
43
|
+
|
44
|
+
##
|
45
|
+
# Raised when a bad requirement is encountered
|
46
|
+
|
47
|
+
class BadRequirementError < ArgumentError; end
|
48
|
+
|
49
|
+
##
|
50
|
+
# Factory method to create a Gem::Requirement object. Input may be
|
51
|
+
# a Version, a String, or nil. Intended to simplify client code.
|
52
|
+
#
|
53
|
+
# If the input is "weird", the default version requirement is
|
54
|
+
# returned.
|
55
|
+
|
56
|
+
def self.create *inputs
|
57
|
+
return new inputs if inputs.length > 1
|
58
|
+
|
59
|
+
input = inputs.shift
|
60
|
+
|
61
|
+
case input
|
62
|
+
when Gel::Support::GemRequirement then
|
63
|
+
input
|
64
|
+
when Gel::Support::GemVersion, Array then
|
65
|
+
new input
|
66
|
+
when '!' then
|
67
|
+
source_set
|
68
|
+
else
|
69
|
+
if input.respond_to? :to_str then
|
70
|
+
new [input.to_str]
|
71
|
+
else
|
72
|
+
default
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# A default "version requirement" can surely _only_ be '>= 0'.
|
79
|
+
|
80
|
+
def self.default
|
81
|
+
new '>= 0'
|
82
|
+
end
|
83
|
+
|
84
|
+
###
|
85
|
+
# A source set requirement, used for Gemfiles and lockfiles
|
86
|
+
|
87
|
+
def self.source_set # :nodoc:
|
88
|
+
SOURCE_SET_REQUIREMENT
|
89
|
+
end
|
90
|
+
|
91
|
+
##
|
92
|
+
# Parse +obj+, returning an <tt>[op, version]</tt> pair. +obj+ can
|
93
|
+
# be a String or a Gem::Version.
|
94
|
+
#
|
95
|
+
# If +obj+ is a String, it can be either a full requirement
|
96
|
+
# specification, like <tt>">= 1.2"</tt>, or a simple version number,
|
97
|
+
# like <tt>"1.2"</tt>.
|
98
|
+
#
|
99
|
+
# parse("> 1.0") # => [">", Gem::Version.new("1.0")]
|
100
|
+
# parse("1.0") # => ["=", Gem::Version.new("1.0")]
|
101
|
+
# parse(Gem::Version.new("1.0")) # => ["=, Gem::Version.new("1.0")]
|
102
|
+
|
103
|
+
def self.parse obj
|
104
|
+
return ["=", obj] if Gel::Support::GemVersion === obj
|
105
|
+
|
106
|
+
unless PATTERN =~ obj.to_s
|
107
|
+
raise BadRequirementError, "Illformed requirement [#{obj.inspect}]"
|
108
|
+
end
|
109
|
+
|
110
|
+
if $1 == ">=" && $2 == "0"
|
111
|
+
DefaultRequirement
|
112
|
+
else
|
113
|
+
[$1 || "=", Gel::Support::GemVersion.new($2)]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
##
|
118
|
+
# An array of requirement pairs. The first element of the pair is
|
119
|
+
# the op, and the second is the Gem::Version.
|
120
|
+
|
121
|
+
attr_reader :requirements #:nodoc:
|
122
|
+
|
123
|
+
##
|
124
|
+
# Constructs a requirement from +requirements+. Requirements can be
|
125
|
+
# Strings, Gem::Versions, or Arrays of those. +nil+ and duplicate
|
126
|
+
# requirements are ignored. An empty set of +requirements+ is the
|
127
|
+
# same as <tt>">= 0"</tt>.
|
128
|
+
|
129
|
+
def initialize *requirements
|
130
|
+
requirements = requirements.flatten
|
131
|
+
requirements.compact!
|
132
|
+
requirements.uniq!
|
133
|
+
|
134
|
+
if requirements.empty?
|
135
|
+
@requirements = [DefaultRequirement]
|
136
|
+
else
|
137
|
+
@requirements = requirements.map! { |r| self.class.parse r }
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
##
|
142
|
+
# Concatenates the +new+ requirements onto this requirement.
|
143
|
+
|
144
|
+
def concat new
|
145
|
+
new = new.flatten
|
146
|
+
new.compact!
|
147
|
+
new.uniq!
|
148
|
+
new = new.map { |r| self.class.parse r }
|
149
|
+
|
150
|
+
@requirements.concat new
|
151
|
+
end
|
152
|
+
|
153
|
+
##
|
154
|
+
# Formats this requirement for use in a Gem::RequestSet::Lockfile.
|
155
|
+
|
156
|
+
def for_lockfile # :nodoc:
|
157
|
+
return if [DefaultRequirement] == @requirements
|
158
|
+
|
159
|
+
list = requirements.sort_by { |_, version|
|
160
|
+
version
|
161
|
+
}.map { |op, version|
|
162
|
+
"#{op} #{version}"
|
163
|
+
}.uniq
|
164
|
+
|
165
|
+
" (#{list.join ', '})"
|
166
|
+
end
|
167
|
+
|
168
|
+
##
|
169
|
+
# true if this gem has no requirements.
|
170
|
+
|
171
|
+
def none?
|
172
|
+
if @requirements.size == 1
|
173
|
+
@requirements[0] == DefaultRequirement
|
174
|
+
else
|
175
|
+
false
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
##
|
180
|
+
# true if the requirement is for only an exact version
|
181
|
+
|
182
|
+
def exact?
|
183
|
+
return false unless @requirements.size == 1
|
184
|
+
@requirements[0][0] == "="
|
185
|
+
end
|
186
|
+
|
187
|
+
def as_list # :nodoc:
|
188
|
+
requirements.map { |op, version| "#{op} #{version}" }.sort
|
189
|
+
end
|
190
|
+
|
191
|
+
def hash # :nodoc:
|
192
|
+
requirements.sort.hash
|
193
|
+
end
|
194
|
+
|
195
|
+
def marshal_dump # :nodoc:
|
196
|
+
[@requirements]
|
197
|
+
end
|
198
|
+
|
199
|
+
def marshal_load array # :nodoc:
|
200
|
+
@requirements = array[0]
|
201
|
+
end
|
202
|
+
|
203
|
+
def yaml_initialize(tag, vals) # :nodoc:
|
204
|
+
vals.each do |ivar, val|
|
205
|
+
instance_variable_set "@#{ivar}", val
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def init_with coder # :nodoc:
|
210
|
+
yaml_initialize coder.tag, coder.map
|
211
|
+
end
|
212
|
+
|
213
|
+
def to_yaml_properties # :nodoc:
|
214
|
+
["@requirements"]
|
215
|
+
end
|
216
|
+
|
217
|
+
def encode_with coder # :nodoc:
|
218
|
+
coder.add 'requirements', @requirements
|
219
|
+
end
|
220
|
+
|
221
|
+
##
|
222
|
+
# A requirement is a prerelease if any of the versions inside of it
|
223
|
+
# are prereleases
|
224
|
+
|
225
|
+
def prerelease?
|
226
|
+
requirements.any? { |r| r.last.prerelease? }
|
227
|
+
end
|
228
|
+
|
229
|
+
def pretty_print q # :nodoc:
|
230
|
+
q.group 1, 'Gel::Support::GemRequirement.new(', ')' do
|
231
|
+
q.pp as_list
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
##
|
236
|
+
# True if +version+ satisfies this Requirement.
|
237
|
+
|
238
|
+
def satisfied_by? version
|
239
|
+
raise ArgumentError, "Need a Gel::Support::GemVersion: #{version.inspect}" unless
|
240
|
+
Gel::Support::GemVersion === version
|
241
|
+
# #28965: syck has a bug with unquoted '=' YAML.loading as YAML::DefaultKey
|
242
|
+
requirements.all? { |op, rv| (OPS[op] || OPS["="]).call version, rv }
|
243
|
+
end
|
244
|
+
|
245
|
+
alias :=== :satisfied_by?
|
246
|
+
alias :=~ :satisfied_by?
|
247
|
+
|
248
|
+
##
|
249
|
+
# True if the requirement will not always match the latest version.
|
250
|
+
|
251
|
+
def specific?
|
252
|
+
return true if @requirements.length > 1 # GIGO, > 1, > 2 is silly
|
253
|
+
|
254
|
+
not %w[> >=].include? @requirements.first.first # grab the operator
|
255
|
+
end
|
256
|
+
|
257
|
+
def to_s # :nodoc:
|
258
|
+
as_list.join ", "
|
259
|
+
end
|
260
|
+
|
261
|
+
def == other # :nodoc:
|
262
|
+
Gel::Support::GemRequirement === other and to_s == other.to_s
|
263
|
+
end
|
264
|
+
end
|