gel 0.3.0 → 0.8.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +26 -3
  3. data/RELEASING.md +12 -0
  4. data/exe/gel +4 -2
  5. data/gemlib/gel/stub.rb +20 -0
  6. data/lib/gel/catalog/common.rb +4 -2
  7. data/lib/gel/catalog/compact_index.rb +6 -10
  8. data/lib/gel/catalog/dependency_index.rb +10 -10
  9. data/lib/gel/catalog/legacy_index.rb +4 -6
  10. data/lib/gel/catalog/marshal_hacks.rb +2 -0
  11. data/lib/gel/catalog.rb +33 -52
  12. data/lib/gel/catalog_set.rb +100 -0
  13. data/lib/gel/command/help.rb +13 -2
  14. data/lib/gel/command/lock.rb +3 -3
  15. data/lib/gel/command/open.rb +24 -0
  16. data/lib/gel/command/shell_setup.rb +11 -8
  17. data/lib/gel/command/stub.rb +45 -2
  18. data/lib/gel/command/version.rb +7 -0
  19. data/lib/gel/command.rb +43 -6
  20. data/lib/gel/compatibility/rubygems.rb +10 -197
  21. data/lib/gel/compatibility.rb +2 -2
  22. data/lib/gel/config.rb +41 -7
  23. data/lib/gel/db.rb +93 -83
  24. data/lib/gel/direct_gem.rb +16 -4
  25. data/lib/gel/environment.rb +542 -249
  26. data/lib/gel/error.rb +156 -24
  27. data/lib/gel/gemfile_parser.rb +74 -12
  28. data/lib/gel/gemspec_parser.rb +26 -7
  29. data/lib/gel/git_catalog.rb +15 -3
  30. data/lib/gel/git_depot.rb +62 -28
  31. data/lib/gel/httpool.rb +5 -2
  32. data/lib/gel/installer.rb +61 -23
  33. data/lib/gel/lock_loader.rb +87 -112
  34. data/lib/gel/lock_parser.rb +23 -31
  35. data/lib/gel/locked_store.rb +30 -21
  36. data/lib/gel/multi_store.rb +13 -4
  37. data/lib/gel/null_solver.rb +67 -0
  38. data/lib/gel/package/abortable.rb +18 -0
  39. data/lib/gel/package/installer.rb +124 -49
  40. data/lib/gel/package.rb +21 -4
  41. data/lib/gel/path_catalog.rb +1 -1
  42. data/lib/gel/pinboard.rb +4 -2
  43. data/lib/gel/platform.rb +38 -0
  44. data/lib/gel/pub_grub/package.rb +67 -0
  45. data/lib/gel/pub_grub/preference_strategy.rb +10 -6
  46. data/lib/gel/pub_grub/solver.rb +37 -0
  47. data/lib/gel/pub_grub/source.rb +64 -92
  48. data/lib/gel/resolved_gem_set.rb +234 -0
  49. data/lib/gel/runtime.rb +3 -3
  50. data/lib/gel/set.rb +62 -0
  51. data/lib/gel/stdlib.rb +83 -0
  52. data/lib/gel/store.rb +94 -25
  53. data/lib/gel/store_catalog.rb +2 -2
  54. data/lib/gel/store_gem.rb +54 -6
  55. data/lib/gel/stub_set.rb +32 -2
  56. data/lib/gel/support/cgi_escape.rb +34 -0
  57. data/lib/gel/support/gem_platform.rb +0 -2
  58. data/lib/gel/support/sha512.rb +142 -0
  59. data/lib/gel/support/tar/tar_writer.rb +2 -2
  60. data/lib/gel/tail_file.rb +2 -1
  61. data/lib/gel/util.rb +108 -0
  62. data/lib/gel/vendor/pstore.rb +3 -0
  63. data/lib/gel/vendor/pub_grub.rb +3 -0
  64. data/lib/gel/vendor/ruby_digest.rb +3 -0
  65. data/lib/gel/vendor_catalog.rb +38 -0
  66. data/lib/gel/version.rb +1 -1
  67. data/lib/gel.rb +15 -0
  68. data/man/man1/gel-exec.1 +1 -1
  69. data/man/man1/gel-install.1 +1 -1
  70. data/man/man1/gel.1 +14 -1
  71. data/{lib/gel/compatibility → slib}/bundler/cli.rb +0 -0
  72. data/{lib/gel/compatibility → slib}/bundler/friendly_errors.rb +0 -0
  73. data/{lib/gel/compatibility/rubygems/dependency_installer.rb → slib/bundler/gem_helper.rb} +0 -0
  74. data/slib/bundler/gem_tasks.rb +0 -0
  75. data/{lib/gel/compatibility → slib}/bundler/setup.rb +0 -0
  76. data/{lib/gel/compatibility → slib}/bundler.rb +39 -3
  77. data/{lib/gel/compatibility → slib}/rubygems/command.rb +0 -0
  78. data/slib/rubygems/dependency_installer.rb +12 -0
  79. data/{lib/gel/compatibility → slib}/rubygems/gem_runner.rb +0 -0
  80. data/slib/rubygems/package.rb +6 -0
  81. data/slib/rubygems/package_task.rb +7 -0
  82. data/slib/rubygems/specification.rb +0 -0
  83. data/slib/rubygems/version.rb +0 -0
  84. data/slib/rubygems.rb +297 -0
  85. data/vendor/pstore/LICENSE.txt +22 -0
  86. data/vendor/pstore/lib/pstore.rb +488 -0
  87. data/vendor/pub_grub/LICENSE.txt +21 -0
  88. data/vendor/pub_grub/lib/pub_grub/assignment.rb +20 -0
  89. data/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +183 -0
  90. data/vendor/pub_grub/lib/pub_grub/failure_writer.rb +182 -0
  91. data/vendor/pub_grub/lib/pub_grub/incompatibility.rb +143 -0
  92. data/vendor/pub_grub/lib/pub_grub/package.rb +35 -0
  93. data/vendor/pub_grub/lib/pub_grub/partial_solution.rb +121 -0
  94. data/vendor/pub_grub/lib/pub_grub/rubygems.rb +45 -0
  95. data/vendor/pub_grub/lib/pub_grub/solve_failure.rb +17 -0
  96. data/vendor/pub_grub/lib/pub_grub/static_package_source.rb +53 -0
  97. data/vendor/pub_grub/lib/pub_grub/term.rb +105 -0
  98. data/vendor/pub_grub/lib/pub_grub/version.rb +3 -0
  99. data/vendor/pub_grub/lib/pub_grub/version_constraint.rb +124 -0
  100. data/vendor/pub_grub/lib/pub_grub/version_range.rb +399 -0
  101. data/vendor/pub_grub/lib/pub_grub/version_solver.rb +247 -0
  102. data/vendor/pub_grub/lib/pub_grub/version_union.rb +174 -0
  103. data/vendor/pub_grub/lib/pub_grub.rb +31 -0
  104. data/vendor/ruby-digest/UNLICENSE +24 -0
  105. data/vendor/ruby-digest/lib/ruby_digest.rb +812 -0
  106. metadata +95 -19
@@ -1,51 +1,46 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "pub_grub"
4
- require "pub_grub/basic_package_source"
5
- require "pub_grub/rubygems"
3
+ require_relative "../vendor/pub_grub"
4
+ require_relative "../../../vendor/pub_grub/lib/pub_grub/rubygems"
6
5
 
7
- module Gel::PubGrub
8
- class Source < ::PubGrub::BasicPackageSource
9
- Spec = Struct.new(:catalog, :name, :version, :info) do
10
- def gem_version
11
- @gem_version ||= Gel::Support::GemVersion.new(version)
12
- end
13
- end
6
+ require_relative "package"
7
+ require_relative "../platform"
14
8
 
15
- attr_reader :root, :root_version
9
+ module Gel::PubGrub
10
+ class Source < Gel::Vendor::PubGrub::BasicPackageSource
11
+ attr_reader :root
16
12
 
17
- def initialize(gemfile, catalogs, active_platforms, preference_strategy)
13
+ def initialize(gemfile, catalog_set, active_platforms, preference_strategy)
18
14
  @gemfile = gemfile
19
- @catalogs = catalogs
15
+ @catalog_set = catalog_set
20
16
  @active_platforms = active_platforms
21
17
  @preference_strategy = preference_strategy
22
18
 
23
- @packages = Hash.new {|h, k| h[k] = PubGrub::Package.new(k) }
24
- @root = PubGrub::Package.root
25
- @root_version = PubGrub::Package.root_version
19
+ # pub_grub-0.5.0/lib/pub_grub/basic_package_source.rb:165
20
+ @packages = {}
26
21
 
27
- @cached_specs = Hash.new { |h, k| h[k] = {} }
28
- @specs_by_package_version = {}
22
+ @root = Package::Pseudo.new(:root)
29
23
 
30
24
  super()
31
25
  end
32
26
 
33
- def spec_for_version(package, version)
34
- if package.name =~ /^~/
35
- return Spec.new(nil, package.name, version, [])
27
+ def active_platforms_map
28
+ @active_platforms_map ||= Hash.new(@active_platforms).tap do |result|
29
+ @gemfile.gems.each do |name, _, options|
30
+ if options.key?(:platforms)
31
+ filter = Array(options[:platforms] || ["ruby"]).map(&:to_s)
32
+ result[name] = Gel::Platform.filter(@active_platforms, filter)
33
+ end
34
+ end
36
35
  end
37
-
38
- @specs_by_package_version[package][version.to_s]
39
36
  end
40
37
 
41
38
  def all_versions_for(package)
42
- if package.name =~ /^~/
43
- return [Gem::Version.new("0")]
39
+ if package.is_a?(Package::Pseudo)
40
+ return [Gel::Support::GemVersion.new("0")]
44
41
  end
45
42
 
46
- fetch_package_info(package)
47
-
48
- @specs_by_package_version[package].values.map(&:gem_version)
43
+ @catalog_set.entries_for(package).map(&:gem_version)
49
44
  end
50
45
 
51
46
  def sort_versions_by_preferred(package, sorted_versions)
@@ -62,92 +57,69 @@ module Gel::PubGrub
62
57
  def dependencies_for(package, version)
63
58
  deps = {}
64
59
 
65
- case package.name
66
- when "~arguments"
67
- if @preference_strategy
68
- @preference_strategy.constraints.each do |name, constraints|
69
- deps[name] ||= []
70
- deps[name].concat constraints.flatten
71
- end
72
- end
73
- when /^~/
74
- raise "Unknown pseudo-package"
75
- else
76
- fetch_package_info(package) # probably already done, can't hurt
60
+ if package.is_a?(Package::Pseudo)
61
+ case package.role
62
+ when :root
63
+ deps = { Package::Pseudo.new(:arguments) => [], Package::Pseudo.new(:gemfile) => [] }
77
64
 
78
- spec = @specs_by_package_version[package][version.to_s]
79
- info = spec.info
80
- info = info.select { |p, i| @active_platforms.include?(p) }
65
+ when :gemfile
66
+ @gemfile.gems.each do |name, constraints, _|
67
+ platforms = active_platforms_map[name]
68
+ platforms = [nil] if platforms.empty?
81
69
 
82
- info.flat_map { |_, i| i[:dependencies] }.each do |n, cs|
83
- deps[n] ||= []
84
- deps[n].concat cs
85
- end
70
+ platforms.each do |platform|
71
+ (deps[Package.new(name, platform)] ||= []).concat(constraints.flatten)
72
+ end
73
+ end
86
74
 
87
- # FIXME: ruby_constraints ???
88
- end
75
+ deps.values.each(&:uniq!)
89
76
 
90
- deps
91
- end
92
-
93
- def root_dependencies
94
- deps = { "~arguments" => [] }
77
+ when :arguments
78
+ if @preference_strategy
79
+ @preference_strategy.constraints.each do |name, constraints|
80
+ @active_platforms.each do |platform|
81
+ (deps[Package.new(name, platform)] ||= []).concat(constraints.flatten)
82
+ end
83
+ end
84
+ end
95
85
 
96
- @gemfile.gems.select do |_, _, options|
97
- next true unless platforms = options[:platforms]
98
- !([*platforms] & [:ruby, :mri]).empty?
99
- end.each do |name, constraints, _|
100
- deps[name] ||= []
101
- deps[name].concat constraints.flatten
86
+ else
87
+ raise "Unknown pseudo-package #{package.inspect}"
88
+ end
89
+ else
90
+ @catalog_set.dependencies_for(package, version).each do |n, cs|
91
+ (deps[Package.new(n, package.platform)] ||= []).concat(cs.flatten)
92
+ end
102
93
  end
103
94
 
104
- deps.values.each(&:uniq!)
105
-
106
95
  deps
107
96
  end
108
97
 
109
98
  def parse_dependency(package, requirement)
110
- ::PubGrub::VersionConstraint.new(@packages[package], range: to_range(requirement))
99
+ Gel::Vendor::PubGrub::VersionConstraint.new(package, range: to_range(requirement))
111
100
  end
112
101
 
113
- private
114
-
115
- def fetch_package_info(package)
116
- return if @specs_by_package_version.key?(package)
117
-
118
- specs = []
119
- @catalogs.each do |catalog|
120
- if catalog.nil?
121
- break unless specs.empty?
122
- next
123
- end
124
-
125
- if info = catalog.gem_info(package.name)
126
- @cached_specs[catalog][package.name] ||=
127
- begin
128
- grouped_versions = info.to_a.map do |full_version, attributes|
129
- version, platform = full_version.split("-", 2)
130
- platform ||= "ruby"
131
- [version, platform, attributes]
132
- end.group_by(&:first)
102
+ def incompatibilities_for(package, version)
103
+ result = super
133
104
 
134
- grouped_versions.map { |version, tuples| Spec.new(catalog, package.name, version, tuples.map { |_, p, a| [p, a] }) }
135
- end
105
+ unless package.is_a?(Package::Pseudo)
106
+ other_platforms = @active_platforms - [package.platform]
136
107
 
137
- specs.concat @cached_specs[catalog][package.name]
108
+ self_constraint = Gel::Vendor::PubGrub::VersionConstraint.new(package, range: Gel::Vendor::PubGrub::VersionRange.new(min: version, max: version, include_min: true, include_max: true))
109
+ result += other_platforms.map do |other_platform|
110
+ other_constraint = Gel::Vendor::PubGrub::VersionConstraint.new(Package.new(package.name, other_platform), range: Gel::Vendor::PubGrub::VersionUnion.new([Gel::Vendor::PubGrub::VersionRange.new(max: version), Gel::Vendor::PubGrub::VersionRange.new(min: version)]))
111
+ Gel::Vendor::PubGrub::Incompatibility.new([Gel::Vendor::PubGrub::Term.new(self_constraint, true), Gel::Vendor::PubGrub::Term.new(other_constraint, true)], cause: :dependency)
138
112
  end
139
113
  end
140
114
 
141
- @specs_by_package_version[package] = {}
142
- specs.each do |spec|
143
- # TODO: are we going to find specs in multiple catalogs this way?
144
- @specs_by_package_version[package][spec.version] = spec
145
- end
115
+ result
146
116
  end
147
117
 
118
+ private
119
+
148
120
  def to_range(constraints)
149
121
  requirement = Gel::Support::GemRequirement.new(constraints)
150
- ::PubGrub::RubyGems.requirement_to_range(requirement)
122
+ Gel::Vendor::PubGrub::RubyGems.requirement_to_range(requirement)
151
123
  end
152
124
  end
153
125
  end
@@ -0,0 +1,234 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "set"
4
+
5
+ class Gel::ResolvedGemSet
6
+ class ResolvedGem
7
+ attr_reader :name, :version, :platform, :deps, :set
8
+
9
+ def initialize(name, version, platform, deps, set:, catalog: nil)
10
+ @name = name
11
+ @version = version
12
+ @platform = platform
13
+ @deps = deps
14
+
15
+ @set = set
16
+ @catalog = catalog
17
+ end
18
+
19
+ def catalog
20
+ @catalog || set.catalog_for(self)
21
+ end
22
+
23
+ def full_version
24
+ if platform
25
+ "#{version}-#{platform}"
26
+ else
27
+ version
28
+ end
29
+ end
30
+ end
31
+
32
+ attr_reader :filename
33
+
34
+ attr_writer :server_catalogs
35
+
36
+ attr_accessor :catalog_uris
37
+ attr_accessor :gems
38
+ attr_accessor :platforms
39
+ attr_accessor :ruby_version
40
+ attr_accessor :bundler_version
41
+ attr_accessor :dependencies
42
+
43
+ def initialize(filename = nil)
44
+ @filename = filename
45
+
46
+ @gems = {}
47
+ end
48
+
49
+ def catalog_for(resolved_gem)
50
+ # FIXME
51
+ end
52
+
53
+ def self.load(filename, git_depot: nil)
54
+ result = new(filename)
55
+
56
+ result.catalog_uris = Gel::Set.new
57
+
58
+ Gel::LockParser.new.parse(File.read(filename)).each do |(section, body)|
59
+ case section
60
+ when "GEM", "PATH", "GIT"
61
+ case section
62
+ when "GEM"
63
+ catalog = nil
64
+
65
+ body["remote"]&.each do |remote|
66
+ result.catalog_uris << remote
67
+ end
68
+ when "PATH"
69
+ require_relative "path_catalog"
70
+ catalog = Gel::PathCatalog.new(body["remote"].first)
71
+ when "GIT"
72
+ ref_type = [:branch, :tag, :ref].find { |t| body[t.to_s] } || :ref
73
+ require_relative "git_catalog"
74
+ catalog = Gel::GitCatalog.new(git_depot, body["remote"].first, ref_type, body[ref_type.to_s]&.first, body["revision"]&.first)
75
+ end
76
+
77
+ specs = body["specs"]
78
+ specs.each do |gem_spec, dep_specs|
79
+ gem_spec =~ /\A(.+) \(([^-]+)(?:-(.+))?\)\z/
80
+ name, version, platform = $1, $2, $3
81
+
82
+ if dep_specs
83
+ deps = dep_specs.map do |spec|
84
+ spec =~ /\A(.+?)(?: \((.+)\))?\z/
85
+ [$1, $2 ? $2.split(", ") : []]
86
+ end
87
+ else
88
+ deps = []
89
+ end
90
+
91
+ (result.gems[name] ||= []) << ResolvedGem.new(name, version, platform, deps, set: result, catalog: catalog)
92
+ end
93
+ when "PLATFORMS"
94
+ result.platforms = body
95
+ when "DEPENDENCIES"
96
+ result.dependencies = body.map { |name| name.chomp("!") }
97
+ when "RUBY VERSION"
98
+ result.ruby_version = body.first
99
+ when "BUNDLED WITH"
100
+ result.bundler_version = body.first
101
+ else
102
+ warn "Unknown lockfile section #{section.inspect}"
103
+ end
104
+ end
105
+
106
+ result
107
+ end
108
+
109
+ def server_catalogs
110
+ @server_catalogs ||=
111
+ begin
112
+ require_relative "catalog"
113
+
114
+ remote_catalogs = catalog_uris.map { |uri| Gel::Catalog.new(uri, work_pool: catalog_pool) }
115
+
116
+ vendor_path = File.expand_path("../vendor/cache", filename)
117
+ if Dir.exist?(vendor_path)
118
+ require_relative "vendor_catalog"
119
+
120
+ vendor_catalog = Gel::VendorCatalog.new(vendor_path)
121
+ vendor_catalog.prepare
122
+ [vendor_catalog] + remote_catalogs
123
+ else
124
+ remote_catalogs
125
+ end
126
+ end
127
+ end
128
+
129
+ def gem_names
130
+ @gems.keys
131
+ end
132
+
133
+ def dependency_names
134
+ dependencies&.map { |dep| dep.split(" ").first }
135
+ end
136
+
137
+ def dump
138
+ lock_content = []
139
+
140
+ output_specs_for = lambda do |results|
141
+ lock_content << " specs:"
142
+ results.each do |resolved_gem|
143
+ next if resolved_gem.name == "bundler" || resolved_gem.name == "ruby"
144
+
145
+ lock_content << " #{resolved_gem.name} (#{resolved_gem.full_version})"
146
+ sorted_deps = resolved_gem.deps.sort_by { |dep_name, dep_reqs| dep_name }
147
+ sorted_deps.each do |dep_name, dep_reqs|
148
+ if dep_reqs
149
+ lock_content << " #{dep_name} (#{dep_reqs})"
150
+ else
151
+ lock_content << " #{dep_name}"
152
+ end
153
+ end
154
+ end
155
+ end
156
+
157
+ grouped_graph = gems.values.flatten(1).sort_by { |rg| [rg.name, "#{rg.full_version}"] }.group_by { |rg|
158
+ catalog = rg.catalog
159
+ catalog.is_a?(Gel::PathCatalog) || catalog.is_a?(Gel::GitCatalog) ? catalog : nil
160
+ }
161
+ server_gems = grouped_graph.delete(nil)
162
+
163
+ grouped_graph.keys.sort_by do |catalog|
164
+ case catalog
165
+ when Gel::GitCatalog
166
+ [1, catalog.remote, catalog.revision]
167
+ when Gel::PathCatalog
168
+ [2, catalog.path]
169
+ end
170
+ end.each do |catalog|
171
+ case catalog
172
+ when Gel::GitCatalog
173
+ lock_content << "GIT"
174
+ lock_content << " remote: #{catalog.remote}"
175
+ lock_content << " revision: #{catalog.revision}"
176
+ lock_content << " #{catalog.ref_type}: #{catalog.ref}" if catalog.ref
177
+ when Gel::PathCatalog
178
+ lock_content << "PATH"
179
+ lock_content << " remote: #{catalog.path}"
180
+ end
181
+
182
+ output_specs_for.call(grouped_graph[catalog])
183
+ lock_content << ""
184
+ end
185
+
186
+ if server_gems
187
+ lock_content << "GEM"
188
+ server_catalogs.each do |catalog|
189
+ lock_content << " remote: #{catalog}"
190
+ end
191
+ output_specs_for.call(server_gems)
192
+ lock_content << ""
193
+ end
194
+
195
+ if platforms && !platforms.empty?
196
+ lock_content << "PLATFORMS"
197
+ platforms.sort.each do |platform|
198
+ lock_content << " #{platform}"
199
+ end
200
+ lock_content << ""
201
+ end
202
+
203
+ lock_content << "DEPENDENCIES"
204
+ bang_deps = (server_gems&.select { |rg| rg.catalog != server_catalogs.first }&.map(&:name) || []) +
205
+ grouped_graph.values.flatten(1).map(&:name)
206
+ dependencies.each do |dependency|
207
+ dependency_name = dependency.split(" ").first
208
+ bang = "!" if bang_deps.include?(dependency_name)
209
+ lock_content << " #{dependency}#{bang}"
210
+ end
211
+ lock_content << ""
212
+
213
+ if ruby_version
214
+ lock_content << "RUBY VERSION"
215
+ lock_content << " #{ruby_version}"
216
+ lock_content << ""
217
+ end
218
+
219
+ if bundler_version
220
+ lock_content << "BUNDLED WITH"
221
+ lock_content << " #{bundler_version}"
222
+ lock_content << ""
223
+ end
224
+
225
+ lock_content.join("\n")
226
+ end
227
+
228
+ private
229
+
230
+ def catalog_pool
231
+ require_relative "work_pool"
232
+ @catalog_pool ||= Gel::WorkPool.new(8, name: "gel-catalog")
233
+ end
234
+ end
data/lib/gel/runtime.rb CHANGED
@@ -6,8 +6,8 @@ dir = ENV["GEL_STORE"] || "~/.local/gel"
6
6
  dir = File.expand_path(dir)
7
7
 
8
8
  unless Dir.exist?(dir)
9
- require "fileutils"
10
- FileUtils.mkdir_p(dir)
9
+ require_relative "util"
10
+ Gel::Util.mkdir_p(dir)
11
11
  end
12
12
 
13
13
  dir = File.realpath(dir)
@@ -23,5 +23,5 @@ store = Gel::MultiStore.new(dir, stores)
23
23
  Gel::Environment.open(Gel::LockedStore.new(store))
24
24
 
25
25
  if ENV["GEL_LOCKFILE"] && ENV["GEL_LOCKFILE"] != ""
26
- Gel::Environment.activate(output: $stderr)
26
+ Gel::Environment.activate(fast: true, output: $stderr)
27
27
  end
data/lib/gel/set.rb ADDED
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Gel::Set
4
+ include Enumerable
5
+
6
+ def initialize
7
+ @inner = {}
8
+ end
9
+
10
+ def initialize_copy(_original)
11
+ @inner = @inner.dup
12
+ end
13
+
14
+ def each(&block)
15
+ @inner.each_key(&block)
16
+ end
17
+
18
+ def include?(value)
19
+ @inner.key?(value)
20
+ end
21
+
22
+ def size
23
+ @inner.size
24
+ end
25
+
26
+ def add(value)
27
+ @inner[value] = true
28
+ end
29
+ alias << add
30
+
31
+ def delete(value)
32
+ @inner.delete(value)
33
+ end
34
+
35
+ def add?(value)
36
+ if @inner.key?(value)
37
+ false
38
+ else
39
+ @inner[value] = true
40
+ end
41
+ end
42
+
43
+ def merge(other)
44
+ other.each do |value|
45
+ add(value)
46
+ end
47
+ self
48
+ end
49
+
50
+ def subtract(other)
51
+ other.each do |value|
52
+ delete(value)
53
+ end
54
+ self
55
+ end
56
+
57
+ def |(other)
58
+ dup.tap do |result|
59
+ result.merge(other)
60
+ end
61
+ end
62
+ end
data/lib/gel/stdlib.rb ADDED
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rbconfig"
4
+
5
+ class Gel::Stdlib
6
+ PATHS = $LOAD_PATH & (RbConfig::CONFIG.values + [File.expand_path("../../slib", __dir__)])
7
+
8
+ def self.instance
9
+ @instance ||= new
10
+ end
11
+
12
+ def initialize
13
+ @files = {}
14
+ @active = {}
15
+
16
+ PATHS.each do |path|
17
+ path_prefix = Gel::Util.join(path, "")
18
+ exclusions = PATHS.
19
+ select { |nested| nested.start_with?(path_prefix) }.
20
+ map { |x| Gel::Util.join(x, "")[path_prefix.size..-1] }
21
+ exclusions << "rubygems" << "bundler" unless path == File.expand_path("../../slib", __dir__)
22
+
23
+ entry_for_ext = Hash.new { |h, k| h[k] = [k, path].freeze }
24
+ single_entry_for_ext = Hash.new { |h, k| h[k] = [entry_for_ext[k]].freeze }
25
+
26
+ Gel::Util.loadable_files(path).each do |file|
27
+ next if file != "rubygems/deprecate.rb" && exclusions.any? { |exc| file.start_with?(exc) }
28
+
29
+ basename, ext = Gel::Util.split_filename_for_require(file)
30
+
31
+ basename = -basename
32
+ ext = -ext
33
+
34
+ if @files.key?(basename)
35
+ @files[basename] = @files[basename].dup << entry_for_ext[ext]
36
+ else
37
+ @files[basename] = single_entry_for_ext[ext]
38
+ end
39
+ end
40
+ end
41
+
42
+ @builtins = $LOADED_FEATURES.grep(/\A[^\/\\]+\z/)
43
+ @builtins += @builtins.map { |s| Gel::Util.split_filename_for_require(s).first }
44
+
45
+ $LOADED_FEATURES.each do |feat|
46
+ @files.each do |basename, pairs|
47
+ next unless feat.include?(basename)
48
+ pairs.each do |ext, path|
49
+ if feat == Gel::Util.join(path, basename + ext)
50
+ @active[basename] = @active[-(basename + ext)] = true
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ def activate(path)
58
+ @active[path] = true
59
+ end
60
+
61
+ def active?(path)
62
+ @active[path]
63
+ end
64
+
65
+ def resolve(search_name, search_ext)
66
+ if @builtins.include?(search_name)
67
+ if search_ext
68
+ full_name = search_name + search_ext
69
+ if @builtins.include?(full_name)
70
+ return search_name
71
+ end
72
+ else
73
+ return search_name
74
+ end
75
+ end
76
+
77
+ @files[search_name]&.each do |ext, path|
78
+ return Gel::Util.join(path, search_name) if Gel::Util.ext_matches_requested?(ext, search_ext)
79
+ end
80
+
81
+ nil
82
+ end
83
+ end