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.
- checksums.yaml +4 -4
- data/README.md +26 -3
- data/RELEASING.md +12 -0
- data/exe/gel +4 -2
- data/gemlib/gel/stub.rb +20 -0
- data/lib/gel/catalog/common.rb +4 -2
- data/lib/gel/catalog/compact_index.rb +6 -10
- data/lib/gel/catalog/dependency_index.rb +10 -10
- data/lib/gel/catalog/legacy_index.rb +4 -6
- data/lib/gel/catalog/marshal_hacks.rb +2 -0
- data/lib/gel/catalog.rb +33 -52
- data/lib/gel/catalog_set.rb +100 -0
- data/lib/gel/command/help.rb +13 -2
- data/lib/gel/command/lock.rb +3 -3
- data/lib/gel/command/open.rb +24 -0
- data/lib/gel/command/shell_setup.rb +11 -8
- data/lib/gel/command/stub.rb +45 -2
- data/lib/gel/command/version.rb +7 -0
- data/lib/gel/command.rb +43 -6
- data/lib/gel/compatibility/rubygems.rb +10 -197
- data/lib/gel/compatibility.rb +2 -2
- data/lib/gel/config.rb +41 -7
- data/lib/gel/db.rb +93 -83
- data/lib/gel/direct_gem.rb +16 -4
- data/lib/gel/environment.rb +542 -249
- data/lib/gel/error.rb +156 -24
- data/lib/gel/gemfile_parser.rb +74 -12
- data/lib/gel/gemspec_parser.rb +26 -7
- data/lib/gel/git_catalog.rb +15 -3
- data/lib/gel/git_depot.rb +62 -28
- data/lib/gel/httpool.rb +5 -2
- data/lib/gel/installer.rb +61 -23
- data/lib/gel/lock_loader.rb +87 -112
- data/lib/gel/lock_parser.rb +23 -31
- data/lib/gel/locked_store.rb +30 -21
- data/lib/gel/multi_store.rb +13 -4
- data/lib/gel/null_solver.rb +67 -0
- data/lib/gel/package/abortable.rb +18 -0
- data/lib/gel/package/installer.rb +124 -49
- data/lib/gel/package.rb +21 -4
- data/lib/gel/path_catalog.rb +1 -1
- data/lib/gel/pinboard.rb +4 -2
- data/lib/gel/platform.rb +38 -0
- data/lib/gel/pub_grub/package.rb +67 -0
- data/lib/gel/pub_grub/preference_strategy.rb +10 -6
- data/lib/gel/pub_grub/solver.rb +37 -0
- data/lib/gel/pub_grub/source.rb +64 -92
- data/lib/gel/resolved_gem_set.rb +234 -0
- data/lib/gel/runtime.rb +3 -3
- data/lib/gel/set.rb +62 -0
- data/lib/gel/stdlib.rb +83 -0
- data/lib/gel/store.rb +94 -25
- data/lib/gel/store_catalog.rb +2 -2
- data/lib/gel/store_gem.rb +54 -6
- data/lib/gel/stub_set.rb +32 -2
- data/lib/gel/support/cgi_escape.rb +34 -0
- data/lib/gel/support/gem_platform.rb +0 -2
- data/lib/gel/support/sha512.rb +142 -0
- data/lib/gel/support/tar/tar_writer.rb +2 -2
- data/lib/gel/tail_file.rb +2 -1
- data/lib/gel/util.rb +108 -0
- data/lib/gel/vendor/pstore.rb +3 -0
- data/lib/gel/vendor/pub_grub.rb +3 -0
- data/lib/gel/vendor/ruby_digest.rb +3 -0
- data/lib/gel/vendor_catalog.rb +38 -0
- data/lib/gel/version.rb +1 -1
- data/lib/gel.rb +15 -0
- data/man/man1/gel-exec.1 +1 -1
- data/man/man1/gel-install.1 +1 -1
- data/man/man1/gel.1 +14 -1
- data/{lib/gel/compatibility → slib}/bundler/cli.rb +0 -0
- data/{lib/gel/compatibility → slib}/bundler/friendly_errors.rb +0 -0
- data/{lib/gel/compatibility/rubygems/dependency_installer.rb → slib/bundler/gem_helper.rb} +0 -0
- data/slib/bundler/gem_tasks.rb +0 -0
- data/{lib/gel/compatibility → slib}/bundler/setup.rb +0 -0
- data/{lib/gel/compatibility → slib}/bundler.rb +39 -3
- data/{lib/gel/compatibility → slib}/rubygems/command.rb +0 -0
- data/slib/rubygems/dependency_installer.rb +12 -0
- data/{lib/gel/compatibility → slib}/rubygems/gem_runner.rb +0 -0
- data/slib/rubygems/package.rb +6 -0
- data/slib/rubygems/package_task.rb +7 -0
- data/slib/rubygems/specification.rb +0 -0
- data/slib/rubygems/version.rb +0 -0
- data/slib/rubygems.rb +297 -0
- data/vendor/pstore/LICENSE.txt +22 -0
- data/vendor/pstore/lib/pstore.rb +488 -0
- data/vendor/pub_grub/LICENSE.txt +21 -0
- data/vendor/pub_grub/lib/pub_grub/assignment.rb +20 -0
- data/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +183 -0
- data/vendor/pub_grub/lib/pub_grub/failure_writer.rb +182 -0
- data/vendor/pub_grub/lib/pub_grub/incompatibility.rb +143 -0
- data/vendor/pub_grub/lib/pub_grub/package.rb +35 -0
- data/vendor/pub_grub/lib/pub_grub/partial_solution.rb +121 -0
- data/vendor/pub_grub/lib/pub_grub/rubygems.rb +45 -0
- data/vendor/pub_grub/lib/pub_grub/solve_failure.rb +17 -0
- data/vendor/pub_grub/lib/pub_grub/static_package_source.rb +53 -0
- data/vendor/pub_grub/lib/pub_grub/term.rb +105 -0
- data/vendor/pub_grub/lib/pub_grub/version.rb +3 -0
- data/vendor/pub_grub/lib/pub_grub/version_constraint.rb +124 -0
- data/vendor/pub_grub/lib/pub_grub/version_range.rb +399 -0
- data/vendor/pub_grub/lib/pub_grub/version_solver.rb +247 -0
- data/vendor/pub_grub/lib/pub_grub/version_union.rb +174 -0
- data/vendor/pub_grub/lib/pub_grub.rb +31 -0
- data/vendor/ruby-digest/UNLICENSE +24 -0
- data/vendor/ruby-digest/lib/ruby_digest.rb +812 -0
- metadata +95 -19
data/lib/gel/command.rb
CHANGED
@@ -8,16 +8,25 @@ class Gel::Command
|
|
8
8
|
command_line = command_line.dup
|
9
9
|
if command_name = extract_word(command_line)
|
10
10
|
const = command_name.downcase.sub(/^./, &:upcase).gsub(/[-_]./) { |s| s[1].upcase }
|
11
|
-
if
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
if const =~ /\A[a-z]+\z/i
|
12
|
+
if Gel::Command.const_defined?(const, false)
|
13
|
+
command = Gel::Command.const_get(const, false).new
|
14
|
+
command.run(command_line)
|
15
|
+
elsif Gel::Environment.activate_for_executable(["gel-#{command_name}", command_name])
|
16
|
+
command_name = "gel-#{command_name}" if Gel::Environment.find_executable("gel-#{command_name}")
|
17
|
+
command = Gel::Command::Exec.new
|
18
|
+
command.run([command_name, *command_line])
|
19
|
+
else
|
20
|
+
raise Gel::Error::UnknownCommandError.new(command_name: command_name)
|
21
|
+
end
|
22
|
+
elsif stub_name = own_stub_file?(command_name) || other_stub_file?(command_name)
|
16
23
|
command = Gel::Command::Exec.new
|
17
|
-
command.run([
|
24
|
+
command.run([stub_name, *command_line], from_stub: true)
|
18
25
|
else
|
19
26
|
raise Gel::Error::UnknownCommandError.new(command_name: command_name)
|
20
27
|
end
|
28
|
+
elsif flag_constant = flags(command_line).first
|
29
|
+
flag_constant.new.run(command_line)
|
21
30
|
else
|
22
31
|
puts <<~EOF
|
23
32
|
Gel doesn't have a default command; please run `gel install`
|
@@ -68,12 +77,39 @@ class Gel::Command
|
|
68
77
|
end
|
69
78
|
end
|
70
79
|
|
80
|
+
def self.own_stub_file?(path)
|
81
|
+
# If it's our own stub file, we can skip reading and parsing it, and
|
82
|
+
# just trust that the basename is correct.
|
83
|
+
if Gel::Environment.store.stub_set.own_stub?(path)
|
84
|
+
File.basename(path)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.other_stub_file?(path)
|
89
|
+
Gel::Environment.store.stub_set.parse_stub(path)
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.flags(arguments)
|
93
|
+
flag_constants = {
|
94
|
+
"h" => Gel::Command::Help,
|
95
|
+
"help" => Gel::Command::Help,
|
96
|
+
"v" => Gel::Command::Version,
|
97
|
+
"version" => Gel::Command::Version,
|
98
|
+
}
|
99
|
+
|
100
|
+
arguments.map { |word|
|
101
|
+
match = word.match(/-+(?<flag>\w+)/)
|
102
|
+
match && flag_constants[match[:flag]]
|
103
|
+
}.compact
|
104
|
+
end
|
105
|
+
|
71
106
|
# If set to true, an error raised from #run will pass straight up to
|
72
107
|
# ruby instead of being treated as an internal Gel error
|
73
108
|
attr_accessor :reraise
|
74
109
|
end
|
75
110
|
|
76
111
|
require_relative "command/help"
|
112
|
+
require_relative "command/version"
|
77
113
|
require_relative "command/install"
|
78
114
|
require_relative "command/install_gem"
|
79
115
|
require_relative "command/env"
|
@@ -84,3 +120,4 @@ require_relative "command/ruby"
|
|
84
120
|
require_relative "command/stub"
|
85
121
|
require_relative "command/config"
|
86
122
|
require_relative "command/shell_setup"
|
123
|
+
require_relative "command/open"
|
@@ -1,201 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
#
|
4
|
-
#
|
3
|
+
# Deprecation plan: Ship this without a warning for at least one
|
4
|
+
# version, so people with an existing `gel shell-setup`-configured shell
|
5
|
+
# don't get messages immediately after updating.
|
5
6
|
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
module Gem
|
12
|
-
Version = Gel::Support::GemVersion
|
13
|
-
Requirement = Gel::Support::GemRequirement
|
14
|
-
|
15
|
-
class Dependency
|
16
|
-
attr_reader :name
|
17
|
-
attr_reader :requirement
|
18
|
-
attr_reader :type
|
19
|
-
|
20
|
-
def initialize(name, requirement, type)
|
21
|
-
@name = name
|
22
|
-
@requirement = requirement
|
23
|
-
@type = type
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
LoadError = Class.new(::LoadError)
|
28
|
-
|
29
|
-
class Specification
|
30
|
-
def self.find_by_name(name, *requirements)
|
31
|
-
if g = Gel::Environment.find_gem(name, *requirements)
|
32
|
-
new(g)
|
33
|
-
else
|
34
|
-
# TODO: Should probably be a Gel exception instead?
|
35
|
-
raise Gem::LoadError, "Unable to find gem #{name.inspect}" + (requirements.empty? ? "" : " (#{requirements.join(", ")})")
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.each(&block)
|
40
|
-
Gel::Environment.store.each.map { |g| new(g) }.each(&block)
|
41
|
-
end
|
42
|
-
|
43
|
-
def initialize(store_gem)
|
44
|
-
@store_gem = store_gem
|
45
|
-
end
|
46
|
-
|
47
|
-
def name
|
48
|
-
@store_gem.name
|
49
|
-
end
|
50
|
-
|
51
|
-
def version
|
52
|
-
Gem::Version.new(@store_gem.version)
|
53
|
-
end
|
54
|
-
|
55
|
-
def dependencies
|
56
|
-
@store_gem.dependencies.map do |name, pairs|
|
57
|
-
Gem::Dependency.new(name, pairs.map { |op, ver| "#{op} #{ver}" }, :runtime)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
alias runtime_dependencies dependencies
|
61
|
-
|
62
|
-
def gem_dir
|
63
|
-
@store_gem.root
|
64
|
-
end
|
65
|
-
alias full_gem_path gem_dir
|
66
|
-
|
67
|
-
def require_paths
|
68
|
-
base = Pathname.new(gem_dir)
|
69
|
-
|
70
|
-
@store_gem.require_paths.map do |path|
|
71
|
-
Pathname.new(path).relative_path_from(base).to_s
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
class DependencyInstaller
|
77
|
-
def install(name, requirement = nil)
|
78
|
-
require_relative "../catalog"
|
79
|
-
require_relative "../work_pool"
|
80
|
-
|
81
|
-
Gel::WorkPool.new(2) do |work_pool|
|
82
|
-
catalog = Gel::Catalog.new("https://rubygems.org", work_pool: work_pool)
|
83
|
-
|
84
|
-
return Gel::Environment.install_gem([catalog], name, requirement)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def self.try_activate(file)
|
90
|
-
Gel::Environment.resolve_gem_path(file) != file
|
91
|
-
rescue LoadError
|
92
|
-
false
|
93
|
-
end
|
94
|
-
|
95
|
-
def self.ruby
|
96
|
-
RbConfig.ruby
|
97
|
-
end
|
98
|
-
|
99
|
-
def self.win_platform?
|
100
|
-
false
|
101
|
-
end
|
102
|
-
|
103
|
-
def self.loaded_specs
|
104
|
-
result = {}
|
105
|
-
Gel::Environment.activated_gems.each do |name, store_gem|
|
106
|
-
result[name] = Gem::Specification.new(store_gem)
|
107
|
-
end
|
108
|
-
result
|
109
|
-
end
|
110
|
-
|
111
|
-
def self.find_files(pattern)
|
112
|
-
Gel::Environment.store.each.
|
113
|
-
flat_map(&:require_paths).
|
114
|
-
flat_map { |dir| Dir[File.join(dir, pattern)] }
|
115
|
-
end
|
116
|
-
|
117
|
-
def self.refresh
|
118
|
-
# no-op
|
119
|
-
end
|
120
|
-
|
121
|
-
def self.path
|
122
|
-
Gel::Environment.store.paths
|
123
|
-
end
|
124
|
-
|
125
|
-
def self.default_dir
|
126
|
-
path.first
|
127
|
-
end
|
128
|
-
|
129
|
-
def self.activate_bin_path(gem_name, bin_name, version = nil)
|
130
|
-
if gem_name == "bundler" && bin_name == "bundle"
|
131
|
-
# Extra-special case: this is the bundler binstub, we need to
|
132
|
-
# re-exec to hand over.
|
133
|
-
|
134
|
-
ENV["RUBYLIB"] = Gel::Environment.original_rubylib
|
135
|
-
exec RbConfig.ruby, "--", $0, *ARGV
|
136
|
-
end
|
137
|
-
|
138
|
-
if gem_name == "gel" && bin_name == "gel"
|
139
|
-
# Another extra-special case: gel is already activated, but it's
|
140
|
-
# being invoked via a rubygems-installed binstub. We can't
|
141
|
-
# activate gel inside gel, but we also don't need to: we know
|
142
|
-
# exactly which file they need.
|
143
|
-
|
144
|
-
return File.expand_path("../../../exe/gel", __dir__)
|
145
|
-
end
|
146
|
-
|
147
|
-
if g = Gel::Environment.activated_gems[gem_name]
|
148
|
-
Gel::Environment.gem g.name, version if version
|
149
|
-
elsif g = Gel::Environment.find_gem(gem_name, *version) do |g|
|
150
|
-
g.executables.include?(bin_name)
|
151
|
-
end
|
152
|
-
|
153
|
-
Gel::Environment.gem g.name, g.version
|
154
|
-
elsif g = Gel::Environment.find_gem(gem_name, *version)
|
155
|
-
raise "#{g.name} (#{g.version}) doesn't contain executable #{bin_name.inspect}"
|
156
|
-
elsif version && Gel::Environment.find_gem(gem_name)
|
157
|
-
raise "#{gem_name} (#{version}) not available"
|
158
|
-
else
|
159
|
-
raise "Unknown gem #{gem_name.inspect}"
|
160
|
-
end
|
161
|
-
|
162
|
-
Gel::Environment.find_executable(bin_name, g.name, g.version)
|
163
|
-
rescue => ex
|
164
|
-
# This method may be our entry-point, if we're being invoked by a
|
165
|
-
# rubygems binstub. Detect that situation, and provide nicer error
|
166
|
-
# reporting.
|
167
|
-
|
168
|
-
raise unless locations = caller_locations(2, 2)
|
169
|
-
raise unless locations.size == 1
|
170
|
-
raise unless path = locations.first.absolute_path
|
171
|
-
raise unless File.exist?(path) && File.readable?(path)
|
172
|
-
raise unless File.open(path, "rb") { |f| f.read(1024).include?("\n# This file was generated by RubyGems.\n") }
|
173
|
-
|
174
|
-
require_relative "../command"
|
175
|
-
Gel::Command.handle_error(ex)
|
176
|
-
end
|
177
|
-
|
178
|
-
def self.bin_path(gem_name, bin_name, version = nil)
|
179
|
-
if g = Gel::Environment.activated_gems[gem_name]
|
180
|
-
Gel::Environment.gem g.name, version if version
|
181
|
-
|
182
|
-
Gel::Environment.find_executable(bin_name, g.name, g.version)
|
183
|
-
elsif Gel::Environment.find_gem(gem_name)
|
184
|
-
raise "Gem #{gem_name.inspect} is not active"
|
185
|
-
else
|
186
|
-
raise "Unknown gem #{gem_name.inspect}"
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
def gem(*args)
|
192
|
-
Gel::Environment.gem(*args)
|
193
|
-
end
|
194
|
-
private :gem
|
195
|
-
|
196
|
-
def require(path)
|
197
|
-
super Gel::Environment.resolve_gem_path(path)
|
198
|
-
end
|
199
|
-
private :require
|
7
|
+
# After that, we'll ship the below message for at least one version,
|
8
|
+
# catching anyone whose terminal session is still alive from before the
|
9
|
+
# above, as well as anyone setting RUBYLIB manually.
|
10
|
+
#
|
11
|
+
# Finally, we can remove this file and surrounding directory entirely.
|
200
12
|
|
201
|
-
|
13
|
+
#$stderr.puts "Gel: lib/gel/compatibility/ is deprecated; please update your RUBYLIB to point to slib/, or use `gel shell-setup`. Restarting your shell may resolve this warning."
|
14
|
+
require_relative "../compatibility"
|
data/lib/gel/compatibility.rb
CHANGED
data/lib/gel/config.rb
CHANGED
@@ -1,8 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "util"
|
4
|
+
|
5
|
+
##
|
6
|
+
# Reads an optional config file ~/.config/gel/config and injects
|
7
|
+
# authorization info from the environment $GEL_AUTH.
|
8
|
+
#
|
9
|
+
# Environment format:
|
10
|
+
#
|
11
|
+
# GEL_AUTH="https://user@pass:host1/ https://user@pass:host2/"
|
12
|
+
#
|
13
|
+
# Config file format:
|
14
|
+
#
|
15
|
+
# # comment:
|
16
|
+
# context-name: # where context-name in [build]
|
17
|
+
# key: val
|
18
|
+
#
|
19
|
+
# key: val
|
20
|
+
#
|
21
|
+
# Example:
|
22
|
+
#
|
23
|
+
# build:
|
24
|
+
# nokogiri: --libdir=blah
|
25
|
+
#
|
26
|
+
# rails-assets.org: username:password
|
27
|
+
#
|
28
|
+
# ---
|
29
|
+
#
|
30
|
+
# GEL_AUTH="https://user@pass:private-gem-server.local"
|
31
|
+
|
3
32
|
class Gel::Config
|
4
|
-
def initialize
|
5
|
-
@root = File.expand_path(
|
33
|
+
def initialize(root_path = "~/.config/gel")
|
34
|
+
@root = File.expand_path(root_path)
|
6
35
|
@path = File.join(@root, "config")
|
7
36
|
@config = nil
|
8
37
|
end
|
@@ -12,10 +41,6 @@ class Gel::Config
|
|
12
41
|
end
|
13
42
|
|
14
43
|
def [](group = nil, key)
|
15
|
-
if group.nil?
|
16
|
-
group, key = key.split(".", 2)
|
17
|
-
end
|
18
|
-
|
19
44
|
(group ? (config[group.to_s] || {}) : config)[key.to_s]
|
20
45
|
end
|
21
46
|
|
@@ -50,11 +75,20 @@ class Gel::Config
|
|
50
75
|
end
|
51
76
|
end
|
52
77
|
end
|
78
|
+
|
79
|
+
# GEL_AUTH = "http://username:password@host http://username:password@host"
|
80
|
+
if auths = ENV["GEL_AUTH"] then
|
81
|
+
auths.split.each do |auth|
|
82
|
+
auth = URI(auth)
|
83
|
+
result[auth.host] = auth.userinfo
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
53
87
|
result
|
54
88
|
end
|
55
89
|
|
56
90
|
def write(data)
|
57
|
-
|
91
|
+
Gel::Util.mkdir_p(@root)
|
58
92
|
|
59
93
|
tempfile = File.join(@root, ".config.#{Process.pid}")
|
60
94
|
File.open(tempfile, "w", 0644) do |f|
|
data/lib/gel/db.rb
CHANGED
@@ -1,11 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
rescue LoadError
|
6
|
-
end
|
7
|
-
require "pstore"
|
8
|
-
require "pathname"
|
3
|
+
require_relative "util"
|
4
|
+
require_relative "vendor/pstore"
|
9
5
|
|
10
6
|
require "monitor"
|
11
7
|
|
@@ -13,11 +9,7 @@ class Gel::DB
|
|
13
9
|
def self.new(root, name)
|
14
10
|
return super unless self == Gel::DB
|
15
11
|
|
16
|
-
|
17
|
-
SDBM.new(root, name)
|
18
|
-
else
|
19
|
-
PStore.new(root, name)
|
20
|
-
end
|
12
|
+
PStore.new(root, name)
|
21
13
|
end
|
22
14
|
|
23
15
|
def initialize(root, name)
|
@@ -40,6 +32,9 @@ class Gel::DB
|
|
40
32
|
|
41
33
|
def []=(key, value)
|
42
34
|
end
|
35
|
+
|
36
|
+
def delete(key)
|
37
|
+
end
|
43
38
|
end
|
44
39
|
|
45
40
|
module Gel::DB::AutoTransaction
|
@@ -133,6 +128,14 @@ module Gel::DB::AutoTransaction
|
|
133
128
|
end
|
134
129
|
end
|
135
130
|
|
131
|
+
def delete(key)
|
132
|
+
if write?
|
133
|
+
super
|
134
|
+
else
|
135
|
+
writing { super }
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
136
139
|
private
|
137
140
|
|
138
141
|
def marshal_dump
|
@@ -144,121 +147,112 @@ module Gel::DB::AutoTransaction
|
|
144
147
|
end
|
145
148
|
end
|
146
149
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
def initialize(root, name)
|
153
|
-
@sdbm = ::SDBM.new("#{root}/#{name}")
|
150
|
+
module Gel::DB::Cache
|
151
|
+
def initialize(*)
|
152
|
+
@cache = nil
|
153
|
+
super
|
154
154
|
end
|
155
155
|
|
156
|
-
def writing
|
157
|
-
|
156
|
+
def writing(&block)
|
157
|
+
@cache = nil
|
158
|
+
super
|
158
159
|
end
|
159
160
|
|
160
|
-
def reading
|
161
|
+
def reading(&block)
|
162
|
+
if @cache.nil?
|
163
|
+
super do
|
164
|
+
cache = {}
|
165
|
+
each_key do |k|
|
166
|
+
cache[k] = self[k]
|
167
|
+
end
|
168
|
+
@cache = cache
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
161
172
|
yield
|
162
173
|
end
|
163
174
|
|
164
175
|
def each_key(&block)
|
165
|
-
@
|
176
|
+
if @cache
|
177
|
+
@cache.each_key(&block)
|
178
|
+
else
|
179
|
+
super
|
180
|
+
end
|
166
181
|
end
|
167
182
|
|
168
183
|
def key?(key)
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
# Retrieve the value from SDBM and handle for when we split
|
174
|
-
# over multiple stores. It is safe to assume that the value
|
175
|
-
# stored will be a marshaled value or a integer implying the
|
176
|
-
# amount of extra stores to retrieve the data string form. A
|
177
|
-
# marshaled store would have special starting delimiter that
|
178
|
-
# is not a decimal. If a number is not found at start of string
|
179
|
-
# then simply load it as a string and you get a value that
|
180
|
-
# is then marshaled.
|
181
|
-
def [](key)
|
182
|
-
value = @sdbm[key.to_s]
|
183
|
-
return nil unless value
|
184
|
-
|
185
|
-
if value =~ /\A~(\d+)\z/
|
186
|
-
value = $1.to_i.times.map do |idx|
|
187
|
-
@sdbm["#{key}#{SAFE_DELIMITER}#{idx}"]
|
188
|
-
end.join
|
184
|
+
if @cache
|
185
|
+
@cache.key?(key)
|
186
|
+
else
|
187
|
+
super
|
189
188
|
end
|
190
|
-
|
191
|
-
return Marshal.load(value)
|
192
189
|
end
|
193
190
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
# so we simply split any string over multiple stores for the edge
|
198
|
-
# case when it reaches this. It's optimised to take advantage of the common
|
199
|
-
# case where this is not needed.
|
200
|
-
# When the edge case is hit, the first value in the storage will be the amount
|
201
|
-
# of extra values stored to hold the split string. This amount is determined by string
|
202
|
-
# size split by the arbitrary limit imposed by SDBM
|
203
|
-
def []=(key, value)
|
204
|
-
return unless value && key
|
205
|
-
|
206
|
-
dump = Marshal.dump(value)
|
207
|
-
count = dump.length / SDBM_MAX_STORE_SIZE
|
208
|
-
|
209
|
-
if count > 0
|
210
|
-
count += 1
|
211
|
-
@sdbm["#{key.to_s}"] = "~#{count}"
|
212
|
-
count.times.map do |idx|
|
213
|
-
@sdbm["#{key.to_s}#{SAFE_DELIMITER}#{idx}"] = dump.slice!(0, SDBM_MAX_STORE_SIZE)
|
214
|
-
end
|
191
|
+
def [](key)
|
192
|
+
if @cache
|
193
|
+
@cache[key]
|
215
194
|
else
|
216
|
-
|
195
|
+
super
|
217
196
|
end
|
218
197
|
end
|
219
198
|
end
|
220
199
|
|
221
200
|
class Gel::DB::PStore < Gel::DB
|
201
|
+
prepend Gel::DB::Cache
|
222
202
|
prepend Gel::DB::AutoTransaction
|
223
203
|
|
224
204
|
def initialize(root, name)
|
225
|
-
@
|
205
|
+
@filename = "#{root}/#{name}.pstore"
|
206
|
+
@pstore = (store if ::File.exist?(@filename))
|
226
207
|
end
|
227
208
|
|
228
209
|
def writing(&block)
|
210
|
+
@pstore ||= store
|
229
211
|
@pstore.transaction(false, &block)
|
230
212
|
end
|
231
213
|
|
232
214
|
def reading(&block)
|
233
|
-
@pstore.
|
215
|
+
@pstore = store if @pstore.nil? && ::File.exist?(@filename)
|
216
|
+
@pstore&.transaction(true, &block)
|
234
217
|
end
|
235
218
|
|
236
219
|
def each_key(&block)
|
237
|
-
@pstore.roots.each(&block)
|
220
|
+
@pstore.roots.each(&block) if @pstore
|
238
221
|
end
|
239
222
|
|
240
223
|
def key?(key)
|
241
|
-
@pstore
|
224
|
+
@pstore&.root?(key.to_s)
|
242
225
|
end
|
243
226
|
|
244
227
|
def [](key)
|
245
|
-
@pstore[key.to_s]
|
228
|
+
@pstore && @pstore[key.to_s]
|
246
229
|
end
|
247
230
|
|
248
231
|
def []=(key, value)
|
249
232
|
@pstore[key.to_s] = value
|
250
233
|
end
|
234
|
+
|
235
|
+
def delete(key)
|
236
|
+
@pstore.delete(key.to_s)
|
237
|
+
end
|
238
|
+
|
239
|
+
private
|
240
|
+
|
241
|
+
def store
|
242
|
+
Gel::Util.mkdir_p(::File.dirname(@filename))
|
243
|
+
Gel::Vendor::PStore.new(@filename, true)
|
244
|
+
end
|
251
245
|
end
|
252
246
|
|
253
247
|
class Gel::DB::File < Gel::DB
|
254
248
|
prepend Gel::DB::AutoTransaction
|
255
249
|
|
256
250
|
def initialize(root, name)
|
257
|
-
@
|
251
|
+
@base = "#{root}/#{name}"
|
258
252
|
end
|
259
253
|
|
260
254
|
def writing
|
261
|
-
|
255
|
+
Gel::Util.mkdir_p(@base)
|
262
256
|
yield
|
263
257
|
end
|
264
258
|
|
@@ -267,28 +261,44 @@ class Gel::DB::File < Gel::DB
|
|
267
261
|
end
|
268
262
|
|
269
263
|
def each_key
|
270
|
-
|
271
|
-
|
264
|
+
return unless Dir.exist?(@base)
|
265
|
+
Dir.each_child(@base) do |child|
|
266
|
+
yield child
|
272
267
|
end
|
273
268
|
end
|
274
269
|
|
275
270
|
def key?(key)
|
276
|
-
|
271
|
+
::File.exist?(path(key))
|
277
272
|
end
|
278
273
|
|
279
274
|
def [](key)
|
280
|
-
child =
|
281
|
-
if
|
282
|
-
Marshal.load(
|
275
|
+
child = path(key)
|
276
|
+
if ::File.exist?(child)
|
277
|
+
Marshal.load(IO.binread(child))
|
283
278
|
end
|
284
279
|
end
|
285
280
|
|
286
281
|
def []=(key, value)
|
287
|
-
child =
|
282
|
+
child = path(key)
|
288
283
|
if value
|
289
|
-
|
290
|
-
elsif
|
291
|
-
|
284
|
+
IO.binwrite child, Marshal.dump(value)
|
285
|
+
elsif ::File.exist?(child)
|
286
|
+
::File.unlink(child)
|
292
287
|
end
|
293
288
|
end
|
289
|
+
|
290
|
+
def delete(key)
|
291
|
+
child = path(key)
|
292
|
+
if ::File.exist?(child)
|
293
|
+
value = Marshal.load(IO.binread(child))
|
294
|
+
::File.unlink(child)
|
295
|
+
value
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
private
|
300
|
+
|
301
|
+
def path(key)
|
302
|
+
::Gel::Util.join(@base, key)
|
303
|
+
end
|
294
304
|
end
|
data/lib/gel/direct_gem.rb
CHANGED
@@ -5,9 +5,19 @@ class Gel::DirectGem < Gel::StoreGem
|
|
5
5
|
Gel::GemspecParser.parse(File.read(filename), filename, isolate: false)
|
6
6
|
end
|
7
7
|
|
8
|
-
def
|
8
|
+
def self.from_block(*args, &block)
|
9
|
+
filename, _lineno = block.source_location
|
10
|
+
|
11
|
+
result = Gel::GemspecParser::Context::Gem::Specification.new(*args, &block)
|
12
|
+
|
13
|
+
new(File.dirname(filename), result.name, loaded_gemspec: result)
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(root, name, version = nil, loaded_gemspec: nil)
|
9
17
|
root = File.expand_path(root)
|
10
|
-
if
|
18
|
+
if loaded_gemspec
|
19
|
+
gemspec = loaded_gemspec
|
20
|
+
elsif File.exist?("#{root}/#{name}.gemspec")
|
11
21
|
gemspec = load_gemspec("#{root}/#{name}.gemspec")
|
12
22
|
elsif File.exist?("#{root}/#{name}/#{name}.gemspec")
|
13
23
|
root = "#{root}/#{name}"
|
@@ -17,13 +27,15 @@ class Gel::DirectGem < Gel::StoreGem
|
|
17
27
|
return
|
18
28
|
end
|
19
29
|
|
30
|
+
require_paths = gemspec.require_paths&.compact || [gemspec.require_path || "lib"]
|
31
|
+
|
20
32
|
info = {
|
21
33
|
bindir: gemspec.bindir || "bin",
|
22
34
|
executables: gemspec.executables,
|
23
|
-
require_paths:
|
35
|
+
require_paths: require_paths,
|
24
36
|
dependencies: gemspec.runtime_dependencies,
|
25
37
|
}
|
26
38
|
|
27
|
-
super(root, name, version || gemspec.version, gemspec.extensions, info)
|
39
|
+
super(root, name, version || Gel::Support::GemVersion.new(gemspec.version).to_s, ("#{root}/ext" if gemspec.extensions.any?), info)
|
28
40
|
end
|
29
41
|
end
|