appraisal 2.1.0 → 2.4.1

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
- SHA1:
3
- metadata.gz: 3b0fc3ea3d75b4caacecc601a02f5cc3dbe9aad9
4
- data.tar.gz: 12d540aa5afe3fe1a12813e21dbccbf65e3c2b9f
2
+ SHA256:
3
+ metadata.gz: 3f28af4a3f925fd52ded81f375ed865a56a844fe20d4bdaf09a4a6fc8c7ad644
4
+ data.tar.gz: 3016386d58c9a22889d2e3e137cec003040f28e75040cc5349fa7d8ef2081c52
5
5
  SHA512:
6
- metadata.gz: bb0850ae7207e6f668668dcfdd0debb6c06b38989ca7bf557530a0e40ecb71aca98404d9d469106b60f2f5469833a40a49743acb96690fb31a492df51f1115b5
7
- data.tar.gz: 6ec513b116b30e95f775df2e5f88d06a5eafad736e922cbd5db3c0f6b2703b655750e9417f700d73cc34f95e30a3c9bd04e55cfd9b9dfe2579fcccd3c73f864a
6
+ metadata.gz: 8f610b40f4e7282377c0d98eb36ee735ca6ecc24daac98995029affb811f2d86e41189628e1667464000ab706392b3ea418411760847bd8a61aea08629e1d461
7
+ data.tar.gz: 709cc7583d98cdaa1ead29f3804f9f02ebf1a7f089af2a751433dc4860748438e6f2f3974eb14fe58ae67dcd1f406b7a00ddf5be6228112258698c67d13595c8
data/.travis.yml CHANGED
@@ -1,22 +1,18 @@
1
- sudo: false
2
-
3
- before_install: gem install bundler
1
+ ---
2
+ before_install: gem install bundler:2.1.4
4
3
 
5
4
  rvm:
6
- - 1.8
7
- - 1.9
8
- - 2.0
9
- - 2.1
10
- - 2.2
11
- - rbx-2
12
- - jruby-19mode
5
+ - 2.3
6
+ - 2.4
7
+ - 2.5
8
+ - 2.6
9
+ - 2.7
10
+ - jruby-9.2.9.0
13
11
  - ruby-head
14
12
  - jruby-head
15
13
 
16
14
  matrix:
17
15
  fast_finish: true
18
16
  allow_failures:
19
- - rvm: rbx-2
20
- - rvm: jruby-19mode
21
17
  - rvm: ruby-head
22
18
  - rvm: jruby-head
data/Gemfile CHANGED
@@ -1,11 +1,6 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
5
  # This here to make sure appraisal works with Rails 3.0.0.
6
- gem 'thor', '~> 0.14.0'
7
-
8
- if RUBY_VERSION < "1.9"
9
- gem "i18n", "~> 0.6.0"
10
- gem "activesupport", "~> 3.2.21"
11
- end
6
+ gem "thor", "~> 0.14.0"
data/README.md CHANGED
@@ -5,7 +5,7 @@ Appraisal
5
5
 
6
6
  Find out what your Ruby gems are worth.
7
7
 
8
- [Build Status Image]: https://secure.travis-ci.org/thoughtbot/appraisal.png?branch=master
8
+ [Build Status Image]: https://secure.travis-ci.org/thoughtbot/appraisal.svg?branch=master
9
9
  [Build Status]: http://travis-ci.org/thoughtbot/appraisal
10
10
 
11
11
  Synopsis
@@ -19,22 +19,23 @@ without interfering with day-to-day development using Bundler.
19
19
  Installation
20
20
  ------------
21
21
 
22
- In your Gemfile:
22
+ In your package's `.gemspec`:
23
23
 
24
- gem "appraisal"
24
+ s.add_development_dependency "appraisal"
25
25
 
26
- Note that gems must be bundled in the global namespace. Bundling gems to a local
27
- location or vendoring plugins is not supported. If you do not want to pollute the
28
- global namespace, one alternative is [RVM's Gemsets](http://rvm.io/gemsets).
26
+ Note that gems must be bundled in the global namespace. Bundling gems to a
27
+ local location or vendoring plugins is not supported. If you do not want to
28
+ pollute the global namespace, one alternative is
29
+ [RVM's Gemsets](http://rvm.io/gemsets).
29
30
 
30
31
  Setup
31
32
  -----
32
33
 
33
- Setting up appraisal requires an Appraisals file (similar to a Gemfile) in your
34
- project root, named "Appraisals" (note the case), and some slight changes to
35
- your project's Rakefile.
34
+ Setting up appraisal requires an `Appraisals` file (similar to a `Gemfile`) in
35
+ your project root, named "Appraisals" (note the case), and some slight changes
36
+ to your project's `Rakefile`.
36
37
 
37
- An Appraisals file consists of several appraisal definitions. An appraisal
38
+ An `Appraisals` file consists of several appraisal definitions. An appraisal
38
39
  definition is simply a list of gem dependencies. For example, to test with a
39
40
  few versions of Rails:
40
41
 
@@ -46,35 +47,29 @@ few versions of Rails:
46
47
  gem "rails", "4.0.0"
47
48
  end
48
49
 
49
- The dependencies in your Appraisals file are combined with dependencies in your
50
- Gemfile, so you don't need to repeat anything that's the same for each
50
+ The dependencies in your `Appraisals` file are combined with dependencies in
51
+ your `Gemfile`, so you don't need to repeat anything that's the same for each
51
52
  appraisal. If something is specified in both the Gemfile and an appraisal, the
52
53
  version from the appraisal takes precedence.
53
54
 
54
- It's also recommended that you setup bundler at the very top of your Rakefile,
55
- so that you don't need to constantly run bundle exec:
56
-
57
- require "rubygems"
58
- require "bundler/setup"
59
-
60
55
  Usage
61
56
  -----
62
57
 
63
58
  Once you've configured the appraisals you want to use, you need to install the
64
59
  dependencies for each appraisal:
65
60
 
66
- appraisal install
61
+ $ bundle exec appraisal install
67
62
 
68
63
  This will resolve, install, and lock the dependencies for that appraisal using
69
64
  bundler. Once you have your dependencies set up, you can run any command in a
70
65
  single appraisal:
71
66
 
72
- appraisal rails-3 rake test
67
+ $ bundle exec appraisal rails-3 rake test
73
68
 
74
69
  This will run `rake test` using the dependencies configured for Rails 3. You can
75
70
  also run each appraisal in turn:
76
71
 
77
- appraisal rake test
72
+ $ bundle exec appraisal rake test
78
73
 
79
74
  If you want to use only the dependencies from your Gemfile, just run `rake
80
75
  test` as normal. This allows you to keep running with the latest versions of
@@ -96,6 +91,18 @@ Note that this may conflict with your CI setup if you decide to split the test
96
91
  into multiple processes by Appraisal and you are using `rake` to run tests by
97
92
  default. Please see **Travis CI Integration** for more detail.
98
93
 
94
+ ### Commands
95
+
96
+ ```bash
97
+ appraisal clean # Remove all generated gemfiles and lockfiles from gemfiles folder
98
+ appraisal generate # Generate a gemfile for each appraisal
99
+ appraisal help [COMMAND] # Describe available commands or one specific command
100
+ appraisal install # Resolve and install dependencies for each appraisal
101
+ appraisal list # List the names of the defined appraisals
102
+ appraisal update [LIST_OF_GEMS] # Remove all generated gemfiles and lockfiles, resolve, and install dependencies again
103
+ appraisal version # Display the version and exit
104
+ ```
105
+
99
106
  Under the hood
100
107
  --------------
101
108
 
@@ -108,6 +115,46 @@ When you prefix a command with `appraisal`, the command is run with the
108
115
  appropriate Gemfile for that appraisal, ensuring the correct dependencies
109
116
  are used.
110
117
 
118
+ Removing Gems using Appraisal
119
+ -------
120
+
121
+ It is common while managing multiple Gemfiles for dependencies to become deprecated and no
122
+ longer necessary, meaning they need to be removed from the Gemfile for a specific `appraisal`.
123
+ To do this, use the `remove_gem` declaration within the necessary `appraise` block in your
124
+ `Appraisals` file.
125
+
126
+ ### Example Usage
127
+
128
+ **Gemfile**
129
+ ```ruby
130
+ gem 'rails', '~> 4.2'
131
+
132
+ group :test do
133
+ gem 'rspec', '~> 4.0'
134
+ gem 'test_after_commit'
135
+ end
136
+ ```
137
+
138
+ **Appraisals**
139
+ ```ruby
140
+ appraise 'rails-5' do
141
+ gem 'rails', '~> 5.2'
142
+
143
+ group :test do
144
+ remove_gem :test_after_commit
145
+ end
146
+ end
147
+ ```
148
+
149
+ Using the `Appraisals` file defined above, this is what the resulting `Gemfile` will look like:
150
+ ```ruby
151
+ gem 'rails', '~> 5.2'
152
+
153
+ group :test do
154
+ gem 'rspec', '~> 4.0'
155
+ end
156
+ ```
157
+
111
158
  Version Control
112
159
  ---------------
113
160
 
@@ -139,15 +186,38 @@ all versions of its dependency, you might have to set a `script` setting:
139
186
  That will make sure that each of the test sub-job are not getting run more than
140
187
  one time.
141
188
 
142
- You can also running your test against multiple versions of Ruby locally, just
189
+ You can also run your tests against multiple versions of Ruby locally, just
143
190
  like running on Travis CI, by using [WWTD].
144
191
 
145
192
  [WWTD]: https://github.com/grosser/wwtd
146
193
 
194
+ Circle CI Integration
195
+ ---------------------
196
+
197
+ In Circle CI you can override the default testing behaviour to customize your
198
+ testing. Using this feature you can configure appraisal to execute your tests.
199
+
200
+ In order to this you can put the following configuration in your circle.yml file:
201
+
202
+ ```yml
203
+ dependencies:
204
+ post:
205
+ - bundle exec appraisal install
206
+ test:
207
+ pre:
208
+ - bundle exec appraisal rake db:create
209
+ - bundle exec appraisal rake db:migrate
210
+ override:
211
+ - bundle exec appraisal rspec
212
+ ```
213
+
214
+ Notice that we are running an rspec suite. You can customize your testing
215
+ command in the `override` section and use your favourite one.
216
+
147
217
  Credits
148
218
  -------
149
219
 
150
- ![thoughtbot](http://thoughtbot.com/images/tm/logo.png)
220
+ ![thoughtbot](http://presskit.thoughtbot.com/images/thoughtbot-logo-for-readmes.svg)
151
221
 
152
222
  Appraisal is maintained and funded by [thoughtbot, inc][thoughtbot]
153
223
 
data/appraisal.gemspec CHANGED
@@ -18,6 +18,8 @@ Gem::Specification.new do |s|
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
20
 
21
+ s.required_ruby_version = ">= 2.3.0"
22
+
21
23
  s.add_runtime_dependency('rake')
22
24
  s.add_runtime_dependency('bundler')
23
25
  s.add_runtime_dependency('thor', '>= 0.14.0')
@@ -7,6 +7,8 @@ require 'pathname'
7
7
  module Appraisal
8
8
  # Represents one appraisal and its dependencies
9
9
  class Appraisal
10
+ DEFAULT_INSTALL_OPTIONS = { "jobs" => 1 }.freeze
11
+
10
12
  attr_reader :name, :gemfile
11
13
 
12
14
  def initialize(name, source_gemfile)
@@ -18,6 +20,10 @@ module Appraisal
18
20
  gemfile.gem(*args)
19
21
  end
20
22
 
23
+ def remove_gem(*args)
24
+ gemfile.remove_gem(*args)
25
+ end
26
+
21
27
  def source(*args, &block)
22
28
  gemfile.source(*args, &block)
23
29
  end
@@ -46,19 +52,25 @@ module Appraisal
46
52
  gemfile.gemspec(options)
47
53
  end
48
54
 
55
+ def git_source(*args, &block)
56
+ gemfile.git_source(*args, &block)
57
+ end
58
+
49
59
  def write_gemfile
50
- ::File.open(gemfile_path, "w") do |file|
60
+ File.open(gemfile_path, "w") do |file|
51
61
  signature = "# This file was generated by Appraisal"
52
62
  file.puts([signature, gemfile.to_s].join("\n\n"))
53
63
  end
54
64
  end
55
65
 
56
- def install(job_size = 1)
57
- command = [
58
- check_command,
59
- "||",
60
- install_command(job_size)
61
- ].flatten.join(" ")
66
+ def install(options = {})
67
+ commands = [install_command(options).join(" ")]
68
+
69
+ if options["without"].nil? || options["without"].empty?
70
+ commands.unshift(check_command.join(" "))
71
+ end
72
+
73
+ command = commands.join(" || ")
62
74
 
63
75
  if Bundler.settings[:path]
64
76
  env = { 'BUNDLE_DISABLE_SHARED_GEMS' => '1' }
@@ -69,8 +81,7 @@ module Appraisal
69
81
  end
70
82
 
71
83
  def update(gems = [])
72
- command, env = update_command(gems)
73
- Command.new(command, :env => env).run
84
+ Command.new(update_command(gems), :gemfile => gemfile_path).run
74
85
  end
75
86
 
76
87
  def gemfile_path
@@ -82,15 +93,15 @@ module Appraisal
82
93
  end
83
94
 
84
95
  def relative_gemfile_path
85
- ::File.join("gemfiles", gemfile_name)
96
+ File.join("gemfiles", gemfile_name)
86
97
  end
87
98
 
88
99
  def relativize
89
100
  current_directory = Pathname.new(Dir.pwd)
90
101
  relative_path = current_directory.relative_path_from(gemfile_root).cleanpath
91
- lockfile_content = ::File.read(lockfile_path)
102
+ lockfile_content = File.read(lockfile_path)
92
103
 
93
- ::File.open(lockfile_path, 'w') do |file|
104
+ File.open(lockfile_path, 'w') do |file|
94
105
  file.write lockfile_content.gsub(/#{current_directory}/, relative_path.to_s)
95
106
  end
96
107
  end
@@ -102,19 +113,21 @@ module Appraisal
102
113
  ['bundle', 'check', gemfile_option]
103
114
  end
104
115
 
105
- def install_command(job_size)
116
+ def install_command(options = {})
106
117
  gemfile_option = "--gemfile='#{gemfile_path}'"
107
- ['bundle', 'install', gemfile_option, bundle_parallel_option(job_size)].compact
118
+ ['bundle', 'install', gemfile_option, bundle_options(options)].compact
108
119
  end
109
120
 
110
121
  def update_command(gems)
111
- env = { "BUNDLE_GEMFILE" => gemfile_path }
112
- command = ['bundle', 'update', *gems].compact
113
- [command, env]
122
+ ['bundle', 'update', *gems].compact
114
123
  end
115
124
 
116
125
  def gemfile_root
117
- Pathname.new(::File.join(Dir.pwd, "gemfiles"))
126
+ project_root + "gemfiles"
127
+ end
128
+
129
+ def project_root
130
+ Pathname.new(Dir.pwd)
118
131
  end
119
132
 
120
133
  def gemfile_name
@@ -129,15 +142,30 @@ module Appraisal
129
142
  name.gsub(/[^\w\.]/, '_')
130
143
  end
131
144
 
132
- def bundle_parallel_option(job_size)
133
- if job_size > 1
145
+ def bundle_options(options)
146
+ full_options = DEFAULT_INSTALL_OPTIONS.dup.merge(options)
147
+ options_strings = []
148
+ jobs = full_options.delete("jobs")
149
+ if jobs > 1
134
150
  if Utils.support_parallel_installation?
135
- "--jobs=#{job_size}"
151
+ options_strings << "--jobs=#{jobs}"
136
152
  else
137
153
  warn 'Your current version of Bundler does not support parallel installation. Please ' +
138
154
  'upgrade Bundler to version >= 1.4.0, or invoke `appraisal` without `--jobs` option.'
139
155
  end
140
156
  end
157
+
158
+ path = full_options.delete("path")
159
+ if path
160
+ relative_path = project_root.join(options["path"])
161
+ options_strings << "--path #{relative_path}"
162
+ end
163
+
164
+ full_options.each do |flag, val|
165
+ options_strings << "--#{flag} #{val}"
166
+ end
167
+
168
+ options_strings.join(" ") if options_strings != []
141
169
  end
142
170
  end
143
171
  end
@@ -4,7 +4,7 @@ require 'appraisal/gemfile'
4
4
 
5
5
  module Appraisal
6
6
  # Loads and parses Appraisals file
7
- class File
7
+ class AppraisalFile
8
8
  attr_reader :appraisals, :gemfile
9
9
 
10
10
  def self.each(&block)
@@ -16,7 +16,7 @@ module Appraisal
16
16
  @gemfile = Gemfile.new
17
17
  @gemfile.load(ENV['BUNDLE_GEMFILE'] || 'Gemfile')
18
18
 
19
- if ::File.exist? path
19
+ if File.exist? path
20
20
  run IO.read(path)
21
21
  else
22
22
  raise AppraisalsNotFound
@@ -1,23 +1,23 @@
1
1
  require "appraisal/dependency_list"
2
- require "appraisal/ordered_hash"
3
2
 
4
3
  module Appraisal
5
4
  class BundlerDSL
6
5
  attr_reader :dependencies
7
6
 
8
- PARTS = %w(source ruby_version git_sources path_sources dependencies groups
7
+ PARTS = %w(source ruby_version gits paths dependencies groups
9
8
  platforms source_blocks gemspec)
10
9
 
11
10
  def initialize
12
11
  @sources = []
13
12
  @ruby_version = nil
14
13
  @dependencies = DependencyList.new
15
- @gemspec = nil
16
- @groups = OrderedHash.new
17
- @platforms = OrderedHash.new
18
- @git_sources = OrderedHash.new
19
- @path_sources = OrderedHash.new
20
- @source_blocks = OrderedHash.new
14
+ @gemspecs = []
15
+ @groups = Hash.new
16
+ @platforms = Hash.new
17
+ @gits = Hash.new
18
+ @paths = Hash.new
19
+ @source_blocks = Hash.new
20
+ @git_sources = {}
21
21
  end
22
22
 
23
23
  def run(&block)
@@ -25,16 +25,22 @@ module Appraisal
25
25
  end
26
26
 
27
27
  def gem(name, *requirements)
28
- @dependencies.add(name, requirements)
28
+ @dependencies.add(name, substitute_git_source(requirements))
29
+ end
30
+
31
+ def remove_gem(name)
32
+ @dependencies.remove(name)
29
33
  end
30
34
 
31
35
  def group(*names, &block)
32
- @groups[names] ||= Group.new(names)
36
+ @groups[names] ||=
37
+ Group.new(names).tap { |g| g.git_sources = @git_sources.dup }
33
38
  @groups[names].run(&block)
34
39
  end
35
40
 
36
41
  def platforms(*names, &block)
37
- @platforms[names] ||= Platform.new(names)
42
+ @platforms[names] ||=
43
+ Platform.new(names).tap { |g| g.git_sources = @git_sources.dup }
38
44
  @platforms[names].run(&block)
39
45
  end
40
46
 
@@ -42,7 +48,8 @@ module Appraisal
42
48
 
43
49
  def source(source, &block)
44
50
  if block_given?
45
- @source_blocks[source] ||= Source.new(source)
51
+ @source_blocks[source] ||=
52
+ Source.new(source).tap { |g| g.git_sources = @git_sources.dup }
46
53
  @source_blocks[source].run(&block)
47
54
  else
48
55
  @sources << source
@@ -54,13 +61,15 @@ module Appraisal
54
61
  end
55
62
 
56
63
  def git(source, options = {}, &block)
57
- @git_sources[source] ||= GitSource.new(source, options)
58
- @git_sources[source].run(&block)
64
+ @gits[source] ||=
65
+ Git.new(source, options).tap { |g| g.git_sources = @git_sources.dup }
66
+ @gits[source].run(&block)
59
67
  end
60
68
 
61
69
  def path(source, options = {}, &block)
62
- @path_sources[source] ||= PathSource.new(source, options)
63
- @path_sources[source].run(&block)
70
+ @paths[source] ||=
71
+ Path.new(source, options).tap { |g| g.git_sources = @git_sources.dup }
72
+ @paths[source].run(&block)
64
73
  end
65
74
 
66
75
  def to_s
@@ -72,9 +81,17 @@ module Appraisal
72
81
  end
73
82
 
74
83
  def gemspec(options = {})
75
- @gemspec = Gemspec.new(options)
84
+ @gemspecs << Gemspec.new(options)
85
+ end
86
+
87
+ def git_source(source, &block)
88
+ @git_sources[source] = block
76
89
  end
77
90
 
91
+ protected
92
+
93
+ attr_writer :git_sources
94
+
78
95
  private
79
96
 
80
97
  def source_entry
@@ -91,25 +108,23 @@ module Appraisal
91
108
 
92
109
  alias_method :ruby_version_entry_for_dup, :ruby_version_entry
93
110
 
94
- [:dependencies, :gemspec].each do |method_name|
95
- class_eval <<-METHODS, __FILE__, __LINE__
96
- private
111
+ def gemspec_entry
112
+ @gemspecs.map(&:to_s).join("\n")
113
+ end
97
114
 
98
- def #{method_name}_entry
99
- if @#{method_name}
100
- @#{method_name}.to_s
101
- end
102
- end
115
+ def gemspec_entry_for_dup
116
+ @gemspecs.map(&:for_dup).join("\n")
117
+ end
103
118
 
104
- def #{method_name}_entry_for_dup
105
- if @#{method_name}
106
- @#{method_name}.for_dup
107
- end
108
- end
109
- METHODS
119
+ def dependencies_entry
120
+ @dependencies.to_s
121
+ end
122
+
123
+ def dependencies_entry_for_dup
124
+ @dependencies.for_dup
110
125
  end
111
126
 
112
- [:git_sources, :path_sources, :platforms, :groups, :source_blocks].
127
+ [:gits, :paths, :platforms, :groups, :source_blocks].
113
128
  each do |method_name|
114
129
  class_eval <<-METHODS, __FILE__, __LINE__
115
130
  private
@@ -127,5 +142,16 @@ module Appraisal
127
142
  def indent(string)
128
143
  string.strip.gsub(/^(.+)$/, ' \1')
129
144
  end
145
+
146
+ def substitute_git_source(requirements)
147
+ requirements.each do |requirement|
148
+ if requirement.is_a?(Hash)
149
+ (requirement.keys & @git_sources.keys).each do |matching_source|
150
+ value = requirement.delete(matching_source)
151
+ requirement[:git] = @git_sources[matching_source].call(value)
152
+ end
153
+ end
154
+ end
155
+ end
130
156
  end
131
157
  end