gel 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Gel::Command::InstallGem < Gel::Command
|
4
|
+
def run(command_line)
|
5
|
+
gem_name, gem_version = command_line
|
6
|
+
|
7
|
+
require_relative "../catalog"
|
8
|
+
require_relative "../work_pool"
|
9
|
+
|
10
|
+
Gel::WorkPool.new(2) do |work_pool|
|
11
|
+
catalog = Gel::Catalog.new("https://rubygems.org", work_pool: work_pool)
|
12
|
+
|
13
|
+
Gel::Environment.install_gem([catalog], gem_name, gem_version, output: $stderr)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Gel::Command::Lock < Gel::Command
|
4
|
+
def run(command_line)
|
5
|
+
options = {}
|
6
|
+
|
7
|
+
mode = :hold
|
8
|
+
strict = false
|
9
|
+
overrides = {}
|
10
|
+
|
11
|
+
until command_line.empty?
|
12
|
+
case argument = command_line.shift
|
13
|
+
when "--strict"; strict = true
|
14
|
+
when "--major"; mode = :major
|
15
|
+
when "--minor"; mode = :minor
|
16
|
+
when "--patch"; mode = :patch
|
17
|
+
when "--hold"; mode = :hold
|
18
|
+
when /\A--lockfile(?:=(.*))?\z/
|
19
|
+
options[:lockfile] = $1 || command_line.shift
|
20
|
+
when /\A((?!-)[A-Za-z0-9_-]+)(?:(?:[\ :\/]|(?=[<>~=]))([<>~=,\ 0-9A-Za-z.-]+))?\z/x
|
21
|
+
overrides[$1] = Gel::Support::GemRequirement.new($2 ? $2.split(/\s+(?=[0-9])|\s*,\s*/) : [])
|
22
|
+
else
|
23
|
+
raise "Unknown argument #{argument.inspect}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
require_relative "../pub_grub/preference_strategy"
|
28
|
+
options[:preference_strategy] = lambda do |loader|
|
29
|
+
Gel::PubGrub::PreferenceStrategy.new(loader, overrides, bump: mode, strict: strict)
|
30
|
+
end
|
31
|
+
|
32
|
+
Gel::Environment.lock(output: $stderr, **options)
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Gel::Command::ShellSetup < Gel::Command
|
4
|
+
def run(command_line)
|
5
|
+
require "shellwords"
|
6
|
+
|
7
|
+
variables = []
|
8
|
+
|
9
|
+
bin_dir = File.expand_path("~/.local/gel/bin")
|
10
|
+
unless ENV.fetch("PATH", "").split(File::PATH_SEPARATOR).include?(bin_dir)
|
11
|
+
puts "PATH=\"#{Shellwords.shellescape bin_dir}#{File::PATH_SEPARATOR}$PATH\""
|
12
|
+
variables << "PATH"
|
13
|
+
end
|
14
|
+
|
15
|
+
lib_dir = File.expand_path("../compatibility", __dir__)
|
16
|
+
unless ENV.fetch("RUBYLIB", "").split(File::PATH_SEPARATOR).include?(lib_dir)
|
17
|
+
puts "RUBYLIB=\"#{Shellwords.shellescape lib_dir}:$RUBYLIB\""
|
18
|
+
variables << "RUBYLIB"
|
19
|
+
end
|
20
|
+
|
21
|
+
unless variables.empty?
|
22
|
+
puts "export #{variables.join(" ")}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Gel::Command::Stub < Gel::Command
|
4
|
+
def run(command_line)
|
5
|
+
stub_command, _path, *arguments = command_line
|
6
|
+
|
7
|
+
command = Gel::Command::Exec.new
|
8
|
+
command.run([stub_command, *arguments], from_stub: true)
|
9
|
+
ensure
|
10
|
+
self.reraise = command.reraise if command
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Gel::Command::Update < Gel::Command
|
4
|
+
def run(command_line)
|
5
|
+
# Mega update mode
|
6
|
+
command_line = ["--major"] if command_line.empty?
|
7
|
+
|
8
|
+
Gel::Command::Lock.new.run(command_line)
|
9
|
+
Gel::Environment.activate(install: true, output: $stderr)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bundler
|
4
|
+
def self.setup
|
5
|
+
Gel::Environment.activate(output: $stderr)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.require(*groups)
|
9
|
+
Gel::Environment.require_groups(*groups)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.default_lockfile
|
13
|
+
Pathname.new(Gel::Environment.lockfile_name)
|
14
|
+
end
|
15
|
+
|
16
|
+
module Rubygems
|
17
|
+
def self.loaded_specs(gem_name)
|
18
|
+
Gem::Specification.new(Gel::Environment.activated_gems[gem_name])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# This is only emulated for bin/spring: we really don't want to try to
|
23
|
+
# actually reproduce Bundler's API
|
24
|
+
class LockfileParser
|
25
|
+
def initialize(content)
|
26
|
+
end
|
27
|
+
|
28
|
+
def specs
|
29
|
+
[]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.rubygems
|
34
|
+
Rubygems
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.with_original_env
|
38
|
+
# TODO
|
39
|
+
yield
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.with_clean_env
|
43
|
+
# TODO
|
44
|
+
yield
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.settings
|
48
|
+
if gemfile = Gel::Environment.gemfile
|
49
|
+
{ "gemfile" => gemfile.filename }
|
50
|
+
else
|
51
|
+
{}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
# We assume this file is only required by the `bundle` executable: if we
|
2
|
+
# get here, we need to re-exec it without Gel on the path, to ensure it
|
3
|
+
# has a full and proper Rubygems environment to work with.
|
4
|
+
|
5
|
+
ENV["RUBYLIB"] = Gel::Environment.original_rubylib
|
6
|
+
exec RbConfig.ruby, "--", $0, *ARGV
|
@@ -0,0 +1,192 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# The goal here is not to be a full drop-in replacement of RubyGems'
|
4
|
+
# API.
|
5
|
+
#
|
6
|
+
# The threshold is basically "things that already-popular/established
|
7
|
+
# gems assume are there without checking".
|
8
|
+
|
9
|
+
require_relative "../runtime"
|
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 g = Gel::Environment.activated_gems[gem_name]
|
139
|
+
Gel::Environment.gem g.name, version if version
|
140
|
+
elsif g = Gel::Environment.find_gem(gem_name, *version) do |g|
|
141
|
+
g.executables.include?(bin_name)
|
142
|
+
end
|
143
|
+
|
144
|
+
Gel::Environment.gem g.name, g.version
|
145
|
+
elsif g = Gel::Environment.find_gem(gem_name, *version)
|
146
|
+
raise "#{g.name} (#{g.version}) doesn't contain executable #{bin_name.inspect}"
|
147
|
+
elsif version && Gel::Environment.find_gem(gem_name)
|
148
|
+
raise "#{gem_name} (#{version}) not available"
|
149
|
+
else
|
150
|
+
raise "Unknown gem #{gem_name.inspect}"
|
151
|
+
end
|
152
|
+
|
153
|
+
Gel::Environment.find_executable(bin_name, g.name, g.version)
|
154
|
+
rescue => ex
|
155
|
+
# This method may be our entry-point, if we're being invoked by a
|
156
|
+
# rubygems binstub. Detect that situation, and provide nicer error
|
157
|
+
# reporting.
|
158
|
+
|
159
|
+
raise unless locations = caller_locations(2, 2)
|
160
|
+
raise unless locations.size == 1
|
161
|
+
raise unless path = locations.first.absolute_path
|
162
|
+
raise unless File.exist?(path) && File.readable?(path)
|
163
|
+
raise unless File.open(path, "rb") { |f| f.read(1024).include?("\n# This file was generated by RubyGems.\n") }
|
164
|
+
|
165
|
+
require_relative "../command"
|
166
|
+
Gel::Command.handle_error(ex)
|
167
|
+
end
|
168
|
+
|
169
|
+
def self.bin_path(gem_name, bin_name, version = nil)
|
170
|
+
if g = Gel::Environment.activated_gems[gem_name]
|
171
|
+
Gel::Environment.gem g.name, version if version
|
172
|
+
|
173
|
+
Gel::Environment.find_executable(bin_name, g.name, g.version)
|
174
|
+
elsif Gel::Environment.find_gem(gem_name)
|
175
|
+
raise "Gem #{gem_name.inspect} is not active"
|
176
|
+
else
|
177
|
+
raise "Unknown gem #{gem_name.inspect}"
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def gem(*args)
|
183
|
+
Gel::Environment.gem(*args)
|
184
|
+
end
|
185
|
+
private :gem
|
186
|
+
|
187
|
+
def require(path)
|
188
|
+
super Gel::Environment.resolve_gem_path(path)
|
189
|
+
end
|
190
|
+
private :require
|
191
|
+
|
192
|
+
require "rubygems/deprecate"
|
File without changes
|
@@ -0,0 +1,6 @@
|
|
1
|
+
# We assume this file is only required by the `gem` executable: if we
|
2
|
+
# get here, we need to re-exec it without Gel on the path, to ensure it
|
3
|
+
# has a full and proper Rubygems environment to work with.
|
4
|
+
|
5
|
+
ENV["RUBYLIB"] = Gel::Environment.original_rubylib
|
6
|
+
exec RbConfig.ruby, "--", $0, *ARGV
|
data/lib/gel/config.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Gel::Config
|
4
|
+
def initialize
|
5
|
+
@root = File.expand_path("~/.config/gel")
|
6
|
+
@path = File.join(@root, "config")
|
7
|
+
@config = nil
|
8
|
+
end
|
9
|
+
|
10
|
+
def config
|
11
|
+
@config ||= read
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](group = nil, key)
|
15
|
+
if group.nil?
|
16
|
+
group, key = key.split(".", 2)
|
17
|
+
end
|
18
|
+
|
19
|
+
(group ? (config[group.to_s] || {}) : config)[key.to_s]
|
20
|
+
end
|
21
|
+
|
22
|
+
def []=(group = nil, key, value)
|
23
|
+
if group.nil?
|
24
|
+
group, key = key.split(".", 2)
|
25
|
+
end
|
26
|
+
|
27
|
+
(group ? (config[group.to_s] ||= {}) : config)[key.to_s] = value.to_s
|
28
|
+
|
29
|
+
write(config)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def read
|
35
|
+
result = {}
|
36
|
+
if File.exist?(@path)
|
37
|
+
context = nil
|
38
|
+
File.read(@path).each_line do |line|
|
39
|
+
line.chomp!
|
40
|
+
if line =~ /\A(\S[^:]*):\z/
|
41
|
+
context = result[$1] = {}
|
42
|
+
elsif line =~ /\A ([^:]*): (.*)\z/
|
43
|
+
context[$1] = $2
|
44
|
+
elsif line =~ /\A([^:]*): (.*)\z/
|
45
|
+
result[$1] = $2
|
46
|
+
elsif line =~ /\A\s*(?:#|\z)/
|
47
|
+
# comment / empty
|
48
|
+
else
|
49
|
+
raise "Unexpected config line #{line.inspect}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
result
|
54
|
+
end
|
55
|
+
|
56
|
+
def write(data)
|
57
|
+
Dir.mkdir(@root) unless Dir.exist?(@root)
|
58
|
+
|
59
|
+
tempfile = File.join(@root, ".config.#{Process.pid}")
|
60
|
+
File.open(tempfile, "w", 0644) do |f|
|
61
|
+
data.each do |key, value|
|
62
|
+
next if value.is_a?(Hash)
|
63
|
+
f.puts("#{key}: #{value}")
|
64
|
+
end
|
65
|
+
|
66
|
+
data.each do |key, value|
|
67
|
+
next unless value.is_a?(Hash)
|
68
|
+
f.puts
|
69
|
+
f.puts("#{key}:")
|
70
|
+
value.each do |subkey, subvalue|
|
71
|
+
f.puts(" #{subkey}: #{subvalue}")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
File.rename(tempfile, @path)
|
77
|
+
ensure
|
78
|
+
File.unlink(tempfile) if File.exist?(tempfile)
|
79
|
+
end
|
80
|
+
end
|