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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b6c69f6e2a7fa19983fee2c4dcf3cc803b34126b98e8fb57df4f7da155736a7
4
- data.tar.gz: 57441eef503b6a6e7b0d3a901ab91306ada2957336aa5734328bd56fdb0da065
3
+ metadata.gz: 7ac61e9a6e0ebdc00fe6c63fe59040cb50f66cfd375f4f4041a1f535f1c8e492
4
+ data.tar.gz: 28812a81b32b67c6d23370974de0963229caef262585ecd91f81d4045a1e407e
5
5
  SHA512:
6
- metadata.gz: eca5ccd35a08b25914a57c2dd691bd3adf483b2f6433c751e8e9db44f4e0dcf4fa3bc3206876c447da247cf769190966dd11da46a074af4f7887b2dcfbfe8626
7
- data.tar.gz: 5aee75b8749c9d7136b50e38b1a9f9c0624e73e20c154628330e0f07691e5f76f2f05d67fe6ab96effeb02793ea3cbabd0b885a56452e5c1754a8714aa082ee3
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
- Install the gem:
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 gel in your current shell:
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
@@ -20,3 +20,4 @@ require_relative "gel/gemspec_parser"
20
20
  require_relative "gel/gemfile_parser"
21
21
  require_relative "gel/lock_parser"
22
22
  require_relative "gel/lock_loader"
23
+ require_relative "gel/version"
@@ -144,7 +144,7 @@ class Gel::Catalog
144
144
  end
145
145
  end
146
146
 
147
- raise "Too many redirects for #{original_uri}"
147
+ raise Gel::Error::TooManyRedirectsError.new(original_uri: original_uri)
148
148
  end
149
149
  end
150
150
 
@@ -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 "Unknown command #{command_name.inspect}"
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|
@@ -46,7 +46,7 @@ class Gel::Config
46
46
  elsif line =~ /\A\s*(?:#|\z)/
47
47
  # comment / empty
48
48
  else
49
- raise "Unexpected config line #{line.inspect}"
49
+ raise Gel::Error::UnexpectedConfigError.new(line: line)
50
50
  end
51
51
  end
52
52
  end
@@ -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 "Cannot activate #{path.inspect}; already activated #{@gemfile.filename.inspect}"
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 "No Gemfile found in #{path.inspect}"
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 "no version of gem #{gem_name.inspect} satifies #{requirements.inspect}"
394
+ raise Gel::Error::NoVersionSatisfyError.new(
395
+ gem_name: gem_name,
396
+ requirements: requirements,
397
+ )
395
398
  else
396
- raise "unknown gem #{gem_name.inspect}"
399
+ raise Gel::Error::UnknownGemError.new(gem_name: gem_name)
397
400
  end
398
401
  end
399
402
 
@@ -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
@@ -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
- raise "Running ruby version #{RUBY_VERSION} does not match requested #{version.inspect}" unless req.satisfied_by?(Gel::Support::GemVersion.new(RUBY_VERSION))
44
- raise "Running ruby engine #{RUBY_ENGINE} does not match requested #{engine.inspect}" unless !engine || RUBY_ENGINE == engine
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
- if file = Dir["#{File.dirname(@result.filename)}/*.gemspec"].first
60
- spec = Gel::GemspecParser.parse(File.read(file), file)
61
- gem spec.name, path: "."
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: :development
81
+ gem name, constraints, group: development_group
64
82
  end
65
83
  end
66
84
  end
@@ -81,7 +81,7 @@ class Gel::GemspecParser
81
81
  end
82
82
 
83
83
  _, status = Process.waitpid2(pid)
84
- raise "Gemspec parse failed" unless status.success?
84
+ raise Gel::Error::ParsedGemspecError unless status.success?
85
85
 
86
86
  write_thread.join
87
87
  Marshal.load read_thread.value
@@ -40,6 +40,7 @@ class Gel::LockLoader
40
40
  yield sym, body, name, version, platform, deps
41
41
  end
42
42
  when "PLATFORMS", "DEPENDENCIES"
43
+ when "RUBY VERSION"
43
44
  when "BUNDLED WITH"
44
45
  else
45
46
  warn "Unknown lockfile section #{section.inspect}"
@@ -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 exited with #{status.exitstatus}" unless status.success?
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
 
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Gel
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
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.2.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-18 00:00:00.000000000 Z
11
+ date: 2019-04-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pub_grub