gel 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +69 -3
- data/lib/gel.rb +1 -0
- data/lib/gel/catalog.rb +1 -1
- data/lib/gel/command.rb +1 -1
- data/lib/gel/compatibility/rubygems.rb +9 -0
- data/lib/gel/config.rb +1 -1
- data/lib/gel/environment.rb +7 -4
- data/lib/gel/error.rb +106 -0
- data/lib/gel/gemfile_parser.rb +25 -7
- data/lib/gel/gemspec_parser.rb +1 -1
- data/lib/gel/lock_loader.rb +1 -0
- data/lib/gel/package/installer.rb +3 -1
- data/lib/gel/store.rb +1 -2
- data/lib/gel/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ac61e9a6e0ebdc00fe6c63fe59040cb50f66cfd375f4f4041a1f535f1c8e492
|
4
|
+
data.tar.gz: 28812a81b32b67c6d23370974de0963229caef262585ecd91f81d4045a1e407e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55fc3ff597234684ef052023204ac18a7fafe8289b88a8dfc896f66f06081bd72d4560092f88c3f74e5054d0030a80732ca30cf2ec7f560806cb260730b2a6ac
|
7
|
+
data.tar.gz: 2631449a64f1b976833b17a632acd28a1f44b3c0821f6e96163ddb53767b0c96a7ccfa02bd49d3b2381ec0738a8aad2c25cb1261f714701f1ae75f8bc645ec74
|
data/README.md
CHANGED
@@ -4,13 +4,79 @@
|
|
4
4
|
|
5
5
|
A modern gem manager.
|
6
6
|
|
7
|
+
Gel is a lightweight alternative to Bundler.
|
8
|
+
|
9
|
+
|
10
|
+
| | Gel | Bundler & Rubygems |
|
11
|
+
|---------|--------------------|--------------------|
|
12
|
+
| install | :white_check_mark: | :white_check_mark: |
|
13
|
+
| update | :white_check_mark: | :white_check_mark: |
|
14
|
+
| lock | :white_check_mark: | :white_check_mark: |
|
15
|
+
| exec | :white_check_mark: | :white_check_mark: |
|
16
|
+
| gem authoring | :x: | :white_check_mark: |
|
17
|
+
| vendoring | :x: | :white_check_mark: |
|
18
|
+
| anything else | :x: | :white_check_mark: |
|
19
|
+
|
20
|
+
This gem is still a work in progress, and things that are still needing some additional improvements include Documentation, UI & Error Messages, and Platform compatibility. We are open to and appreciate any help improving any of these areas.
|
21
|
+
|
22
|
+
## Why Should I Use Gel?
|
23
|
+
|
24
|
+
Gel was written with the goal of improving the performance of common Bundler tasks. Eventually we would like to backport known performance improvements back into Bundler so that everyone can benefit from these improvements, but it is easier to implement and test potential performance improvements in a smaller, more lightweight codebase beforehand.
|
25
|
+
|
26
|
+
Another way that Gel gains a performance benefit over Bundler is simply that Gel includes less features overall. For anyone that doesn't need _all_ the features provided by Bundler, using Gel as a more lightweight gem manager might be beneficial.
|
27
|
+
|
28
|
+
One of the improvements that Gel has over Bundler is being able to take advantage of a new version solver called [Pub Grub](https://medium.com/@nex3/pubgrub-2fb6470504f). Gel utilizes the `pub_grub` gem (https://github.com/jhawthorn/pub_grub) which is a Ruby port of the PubGrub algorithm.
|
29
|
+
|
30
|
+
Some real world examples of the types of performance improvements Gel provides over Bundler are as follows:
|
31
|
+
|
32
|
+
* `% gel exec rake -version`: 55% faster than `bundle`
|
33
|
+
* `% gel exec rails --version`: 60% faster than `bundle`
|
34
|
+
* `% gel exec rails runner nil`: 45% faster than `bundle`
|
35
|
+
|
36
|
+
Comparing using a complex, mature Rails application:
|
37
|
+
|
38
|
+
* `% gel install`: 55% faster than `bundle`
|
39
|
+
* `% gel lock`: 78% faster than `bundle` on first run
|
40
|
+
* `% gel lock`: 95% faster than `bundle` on later runs (cache exists)
|
41
|
+
|
42
|
+
|
43
|
+
Comparing using a simple Gemfile with a complex gem:
|
44
|
+
|
45
|
+
```
|
46
|
+
source "https://rubygems.org"
|
47
|
+
|
48
|
+
gem "tty"
|
49
|
+
```
|
50
|
+
|
51
|
+
* `% gel install`: 70% faster than `bundle`
|
52
|
+
* `% gel lock`: 34% faster than `bundle`
|
53
|
+
|
54
|
+
Comparing using an example Gemfile with gems that showcase a difficult version resolving:
|
55
|
+
|
56
|
+
```
|
57
|
+
source "https://rubygems.org"
|
58
|
+
|
59
|
+
gem "activerecord"
|
60
|
+
gem "quiet_assets"
|
61
|
+
```
|
62
|
+
|
63
|
+
* `% gel lock`: 96% faster than `bundle`
|
64
|
+
|
65
|
+
This example showcases the speed improvements provided by the new PubGrub Version Solving algorithm.
|
66
|
+
|
67
|
+
Note that all of the performance numbers were gathered using just a regular laptop used for common day-to-day development. These numbers were not measured in perfect isolation and your experience may vary.
|
68
|
+
|
7
69
|
## Installation
|
8
70
|
|
9
|
-
|
71
|
+
If you're on a Mac, we recommend that you install via Homebrew:
|
72
|
+
|
73
|
+
$ brew install gel
|
74
|
+
|
75
|
+
Otherwise, you can install Gel as a gem:
|
10
76
|
|
11
77
|
$ gem install gel
|
12
78
|
|
13
|
-
Then, either activate
|
79
|
+
Then, either activate Gel in your current shell:
|
14
80
|
|
15
81
|
$ eval "$(gel shell-setup)"
|
16
82
|
|
@@ -20,7 +86,7 @@ Or add it to your `.bashrc` or `.zshrc` to enable it everywhere:
|
|
20
86
|
|
21
87
|
## Usage
|
22
88
|
|
23
|
-
Use `gel install`, `gel lock`, and `gel exec` as you would the equivalent `bundle` subcommands.
|
89
|
+
Use `gel install`, `gel lock`, `gel update`, and `gel exec` as you would the equivalent `bundle` subcommands.
|
24
90
|
|
25
91
|
## Development
|
26
92
|
|
data/lib/gel.rb
CHANGED
data/lib/gel/catalog.rb
CHANGED
data/lib/gel/command.rb
CHANGED
@@ -16,7 +16,7 @@ class Gel::Command
|
|
16
16
|
command = Gel::Command::Exec.new
|
17
17
|
command.run([command_name, *command_line])
|
18
18
|
else
|
19
|
-
raise
|
19
|
+
raise Gel::Error::UnknownCommandError.new(command_name: command_name)
|
20
20
|
end
|
21
21
|
else
|
22
22
|
puts <<~EOF
|
@@ -135,6 +135,15 @@ module Gem
|
|
135
135
|
exec RbConfig.ruby, "--", $0, *ARGV
|
136
136
|
end
|
137
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
|
+
|
138
147
|
if g = Gel::Environment.activated_gems[gem_name]
|
139
148
|
Gel::Environment.gem g.name, version if version
|
140
149
|
elsif g = Gel::Environment.find_gem(gem_name, *version) do |g|
|
data/lib/gel/config.rb
CHANGED
data/lib/gel/environment.rb
CHANGED
@@ -72,7 +72,7 @@ class Gel::Environment
|
|
72
72
|
|
73
73
|
def self.find_gemfile(path = nil, error: true)
|
74
74
|
if path && @gemfile && @gemfile.filename != File.expand_path(path)
|
75
|
-
raise
|
75
|
+
raise Gel::Error::CannotActivateError.new(path: path, gemfile: @gemfile.filename)
|
76
76
|
end
|
77
77
|
return @gemfile.filename if @gemfile
|
78
78
|
|
@@ -83,7 +83,7 @@ class Gel::Environment
|
|
83
83
|
if File.exist?(path)
|
84
84
|
path
|
85
85
|
elsif error
|
86
|
-
raise
|
86
|
+
raise Gel::Error::NoGemfile.new(path: path)
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
@@ -391,9 +391,12 @@ class Gel::Environment
|
|
391
391
|
end
|
392
392
|
|
393
393
|
if found_any
|
394
|
-
raise
|
394
|
+
raise Gel::Error::NoVersionSatisfyError.new(
|
395
|
+
gem_name: gem_name,
|
396
|
+
requirements: requirements,
|
397
|
+
)
|
395
398
|
else
|
396
|
-
raise
|
399
|
+
raise Gel::Error::UnknownGemError.new(gem_name: gem_name)
|
397
400
|
end
|
398
401
|
end
|
399
402
|
|
data/lib/gel/error.rb
CHANGED
@@ -101,4 +101,110 @@ module Gel::Error
|
|
101
101
|
"No available gem supplies a #{self[:name].inspect} executable"
|
102
102
|
end
|
103
103
|
end
|
104
|
+
|
105
|
+
class TooManyRedirectsError < Gel::UserError
|
106
|
+
def initialize(original_uri:)
|
107
|
+
super
|
108
|
+
end
|
109
|
+
|
110
|
+
def message
|
111
|
+
"Too many redirects for #{self[:original_uri].inspect}"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class UnknownCommandError < Gel::UserError
|
116
|
+
def initialize(command_name:)
|
117
|
+
super
|
118
|
+
end
|
119
|
+
|
120
|
+
def message
|
121
|
+
"Unknown command #{self[:command_name].inspect}"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
class UnexpectedConfigError < Gel::UserError
|
126
|
+
def initialize(line:)
|
127
|
+
super
|
128
|
+
end
|
129
|
+
|
130
|
+
def message
|
131
|
+
"Unexpected config line #{self[:line].inspect}"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
class CannotActivateError < Gel::UserError
|
136
|
+
def initialize(path:, gemfile:)
|
137
|
+
super
|
138
|
+
end
|
139
|
+
|
140
|
+
def message
|
141
|
+
"Cannot activate #{self[:path].inspect}; already activated #{self[:gemfile].inspect}"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
class ExtensionBuildError < Gel::UserError
|
146
|
+
def initialize(program_name:, exitstatus:)
|
147
|
+
super
|
148
|
+
end
|
149
|
+
|
150
|
+
def message
|
151
|
+
"#{self[:program_name].inspect} exited with #{self[:exitstatus].inspect}"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
class NoGemfile < Gel::UserError
|
156
|
+
def initialize(path:)
|
157
|
+
super
|
158
|
+
end
|
159
|
+
|
160
|
+
def message
|
161
|
+
"No Gemfile found in #{self[:path].inspect}"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
class NoVersionSatisfy < Gel::UserError
|
166
|
+
def initialize(gem_name:, requirements:)
|
167
|
+
super
|
168
|
+
end
|
169
|
+
|
170
|
+
def message
|
171
|
+
"no version of gem #{self[:gem_name].inspect} satifies #{self[:requirements].inspect}"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
class UnknownGemError < Gel::UserError
|
176
|
+
def initialize(gem_name:)
|
177
|
+
super
|
178
|
+
end
|
179
|
+
|
180
|
+
def message
|
181
|
+
"Unknown gem #{self[:gem_name].inspect}"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
class MismatchRubyVersionError < Gel::UserError
|
186
|
+
def initialize(running:, requested:)
|
187
|
+
super
|
188
|
+
end
|
189
|
+
|
190
|
+
def message
|
191
|
+
"Running ruby version #{self[:running].inspect} does not match requested #{self[:requested].inspect}"
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
class MismatchRubyEngineError < Gel::UserError
|
196
|
+
def initialize(running:, engine:)
|
197
|
+
super
|
198
|
+
end
|
199
|
+
|
200
|
+
def message
|
201
|
+
"Running ruby engine #{self[:running].inspect} does not match requested #{self[:engine].inspect}"
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
class ParsedGemspecError < Gel::UserError
|
206
|
+
def message
|
207
|
+
"Gemspec parse failed"
|
208
|
+
end
|
209
|
+
end
|
104
210
|
end
|
data/lib/gel/gemfile_parser.rb
CHANGED
@@ -40,8 +40,18 @@ module Gel::GemfileParser
|
|
40
40
|
|
41
41
|
def ruby(version, engine: nil, engine_version: nil)
|
42
42
|
req = Gel::Support::GemRequirement.new(version)
|
43
|
-
|
44
|
-
|
43
|
+
unless req.satisfied_by?(Gel::Support::GemVersion.new(RUBY_VERSION))
|
44
|
+
raise Gel::Error::MismatchRubyVersionError.new(
|
45
|
+
running: RUBY_VERSION,
|
46
|
+
requested: version,
|
47
|
+
)
|
48
|
+
end
|
49
|
+
unless !engine || RUBY_ENGINE == engine
|
50
|
+
raise Gel::Error::MismatchRubyEngineError.new(
|
51
|
+
running: RUBY_ENGINE,
|
52
|
+
engine: engine,
|
53
|
+
)
|
54
|
+
end
|
45
55
|
if engine_version
|
46
56
|
raise "Cannot specify :engine_version without :engine" unless engine
|
47
57
|
req = Gel::Support::GemRequirement.new(version)
|
@@ -55,12 +65,20 @@ module Gel::GemfileParser
|
|
55
65
|
@result.add_gem(name, requirements, options)
|
56
66
|
end
|
57
67
|
|
58
|
-
def gemspec
|
59
|
-
|
60
|
-
|
61
|
-
|
68
|
+
def gemspec(name: nil, path: ".", development_group: :development)
|
69
|
+
dirname = File.expand_path(path, File.dirname(@result.filename))
|
70
|
+
gemspecs = Dir[File.join(dirname, "*.gemspec")]
|
71
|
+
gemspecs.map! { |file| Gel::GemspecParser.parse(File.read(file), file) }
|
72
|
+
gemspecs.select! { |s| s.name == name } if name
|
73
|
+
if gemspecs.empty?
|
74
|
+
raise "No gemspecs at #{dirname}"
|
75
|
+
elsif gemspecs.count > 1
|
76
|
+
raise "Multiple gemspecs at #{dirname}"
|
77
|
+
else
|
78
|
+
spec = gemspecs[0]
|
79
|
+
gem spec.name, path: path
|
62
80
|
spec.development_dependencies.each do |name, constraints|
|
63
|
-
gem name, constraints, group:
|
81
|
+
gem name, constraints, group: development_group
|
64
82
|
end
|
65
83
|
end
|
66
84
|
end
|
data/lib/gel/gemspec_parser.rb
CHANGED
data/lib/gel/lock_loader.rb
CHANGED
@@ -4,6 +4,7 @@ require "fileutils"
|
|
4
4
|
require "pathname"
|
5
5
|
require "rbconfig"
|
6
6
|
require "tempfile"
|
7
|
+
require "shellwords"
|
7
8
|
|
8
9
|
class Gel::Package::Installer
|
9
10
|
def initialize(store)
|
@@ -182,7 +183,7 @@ class Gel::Package::Installer
|
|
182
183
|
File.basename(ext),
|
183
184
|
rake: true,
|
184
185
|
)
|
185
|
-
raise "mkrf_conf
|
186
|
+
raise Gel::Error::ExtensionBuildError.new(program_name: "mkrf_conf", exitstatus: status.exitstatus) unless status.success?
|
186
187
|
end
|
187
188
|
|
188
189
|
status = build_command(
|
@@ -196,6 +197,7 @@ class Gel::Package::Installer
|
|
196
197
|
"rake",
|
197
198
|
rake: true,
|
198
199
|
)
|
200
|
+
raise Gel::Error::ExtensionBuildError.new(program_name: "rake", exitstatus: status.exitstatus) unless status.success?
|
199
201
|
end
|
200
202
|
end
|
201
203
|
|
data/lib/gel/store.rb
CHANGED
@@ -141,7 +141,7 @@ class Gel::Store
|
|
141
141
|
end
|
142
142
|
end
|
143
143
|
|
144
|
-
def each(gem_name = nil)
|
144
|
+
def each(gem_name = nil, &block)
|
145
145
|
return enum_for(__callee__, gem_name) unless block_given?
|
146
146
|
|
147
147
|
if gem_name
|
@@ -159,7 +159,6 @@ class Gel::Store
|
|
159
159
|
gem_names << $1 if k =~ /\Av\/(.*)\z/
|
160
160
|
end
|
161
161
|
|
162
|
-
block = Proc.new
|
163
162
|
gem_names.each do |n|
|
164
163
|
each(n, &block)
|
165
164
|
end
|
data/lib/gel/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gel Authors
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-04-
|
11
|
+
date: 2019-04-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pub_grub
|