appraisal 2.0.1 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +8 -12
- data/Gemfile +2 -7
- data/README.md +93 -23
- data/appraisal.gemspec +3 -1
- data/lib/appraisal/appraisal.rb +57 -24
- data/lib/appraisal/{file.rb → appraisal_file.rb} +2 -2
- data/lib/appraisal/bundler_dsl.rb +66 -33
- data/lib/appraisal/cli.rb +23 -9
- data/lib/appraisal/command.rb +7 -4
- data/lib/appraisal/dependency_list.rb +11 -3
- data/lib/appraisal/gemfile.rb +7 -3
- data/lib/appraisal/{git_source.rb → git.rb} +1 -1
- data/lib/appraisal/{path_source.rb → path.rb} +1 -1
- data/lib/appraisal/source.rb +30 -0
- data/lib/appraisal/task.rb +2 -2
- data/lib/appraisal/travis_ci_helper.rb +7 -6
- data/lib/appraisal/utils.rb +20 -2
- data/lib/appraisal/version.rb +1 -1
- data/spec/acceptance/appraisals_file_bundler_dsl_compatibility_spec.rb +29 -4
- data/spec/acceptance/bundle_with_custom_path_spec.rb +44 -13
- data/spec/acceptance/bundle_without_spec.rb +51 -0
- data/spec/acceptance/cli/install_spec.rb +50 -8
- data/spec/acceptance/cli/update_spec.rb +2 -1
- data/spec/acceptance/gemspec_spec.rb +1 -0
- data/spec/appraisal/{file_spec.rb → appraisal_file_spec.rb} +4 -3
- data/spec/appraisal/appraisal_spec.rb +27 -2
- data/spec/appraisal/dependency_list_spec.rb +19 -0
- data/spec/appraisal/gemfile_spec.rb +22 -8
- data/spec/appraisal/utils_spec.rb +18 -4
- data/spec/support/acceptance_test_helpers.rb +6 -7
- data/spec/support/dependency_helpers.rb +4 -0
- metadata +16 -14
data/lib/appraisal/cli.rb
CHANGED
@@ -19,11 +19,11 @@ module Appraisal
|
|
19
19
|
appraisal, otherwise it runs the EXTERNAL_COMMAND against all appraisals.
|
20
20
|
help
|
21
21
|
|
22
|
-
if
|
22
|
+
if File.exist?('Appraisals')
|
23
23
|
shell.say
|
24
24
|
shell.say 'Available Appraisal(s):'
|
25
25
|
|
26
|
-
|
26
|
+
AppraisalFile.each do |appraisal|
|
27
27
|
shell.say " - #{appraisal.name}"
|
28
28
|
end
|
29
29
|
end
|
@@ -41,11 +41,23 @@ module Appraisal
|
|
41
41
|
method_option 'jobs', :aliases => 'j', :type => :numeric, :default => 1,
|
42
42
|
:banner => 'SIZE',
|
43
43
|
:desc => 'Install gems in parallel using the given number of workers.'
|
44
|
+
method_option 'retry', :type => :numeric, :default => 1,
|
45
|
+
:desc => 'Retry network and git requests that have failed'
|
46
|
+
method_option "without", :banner => "GROUP_NAMES",
|
47
|
+
:desc => "A space-separated list of groups referencing gems to skip " +
|
48
|
+
"during installation. Bundler will remember this option."
|
49
|
+
method_option "full-index", :type => :boolean,
|
50
|
+
:desc => "Run bundle install with the " \
|
51
|
+
"full-index argument."
|
52
|
+
method_option "path", type: :string,
|
53
|
+
desc: "Install gems in the specified directory. " \
|
54
|
+
"Bundler will remember this option."
|
55
|
+
|
44
56
|
def install
|
45
57
|
invoke :generate, [], {}
|
46
58
|
|
47
|
-
|
48
|
-
appraisal.install(options
|
59
|
+
AppraisalFile.each do |appraisal|
|
60
|
+
appraisal.install(options)
|
49
61
|
appraisal.relativize
|
50
62
|
end
|
51
63
|
end
|
@@ -53,7 +65,7 @@ module Appraisal
|
|
53
65
|
desc 'generate', 'Generate a gemfile for each appraisal'
|
54
66
|
method_option "travis", :type => :boolean, :default => false
|
55
67
|
def generate
|
56
|
-
|
68
|
+
AppraisalFile.each do |appraisal|
|
57
69
|
appraisal.write_gemfile
|
58
70
|
end
|
59
71
|
|
@@ -73,14 +85,14 @@ module Appraisal
|
|
73
85
|
def update(*gems)
|
74
86
|
invoke :generate, []
|
75
87
|
|
76
|
-
|
88
|
+
AppraisalFile.each do |appraisal|
|
77
89
|
appraisal.update(gems)
|
78
90
|
end
|
79
91
|
end
|
80
92
|
|
81
93
|
desc 'list', 'List the names of the defined appraisals'
|
82
94
|
def list
|
83
|
-
|
95
|
+
AppraisalFile.new.appraisals.each { |appraisal| puts appraisal.name }
|
84
96
|
end
|
85
97
|
|
86
98
|
desc "version", "Display the version and exit"
|
@@ -91,12 +103,14 @@ module Appraisal
|
|
91
103
|
private
|
92
104
|
|
93
105
|
def method_missing(name, *args, &block)
|
94
|
-
matching_appraisal =
|
106
|
+
matching_appraisal = AppraisalFile.new.appraisals.detect do |appraisal|
|
107
|
+
appraisal.name == name.to_s
|
108
|
+
end
|
95
109
|
|
96
110
|
if matching_appraisal
|
97
111
|
Command.new(args, :gemfile => matching_appraisal.gemfile_path).run
|
98
112
|
else
|
99
|
-
|
113
|
+
AppraisalFile.each do |appraisal|
|
100
114
|
Command.new(ARGV, :gemfile => appraisal.gemfile_path).run
|
101
115
|
end
|
102
116
|
end
|
data/lib/appraisal/command.rb
CHANGED
@@ -41,14 +41,17 @@ module Appraisal
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def ensure_bundler_is_available
|
44
|
-
|
44
|
+
version = Utils.bundler_version
|
45
|
+
unless system %(gem list -i bundler -v #{version})
|
45
46
|
puts ">> Reinstall Bundler into #{ENV["GEM_HOME"]}"
|
46
47
|
|
47
|
-
unless system "gem install bundler"
|
48
|
+
unless system "gem install bundler --version #{version}"
|
48
49
|
puts
|
49
50
|
puts <<-ERROR.strip.gsub(/\s+/, " ")
|
50
|
-
Bundler installation failed.
|
51
|
-
|
51
|
+
Bundler installation failed.
|
52
|
+
Please try running:
|
53
|
+
`GEM_HOME="#{ENV["GEM_HOME"]}" gem install bundler --version #{version}`
|
54
|
+
manually.
|
52
55
|
ERROR
|
53
56
|
exit(1)
|
54
57
|
end
|
@@ -1,14 +1,22 @@
|
|
1
1
|
require 'appraisal/dependency'
|
2
|
-
require "active_support/ordered_hash"
|
3
2
|
|
4
3
|
module Appraisal
|
5
4
|
class DependencyList
|
6
5
|
def initialize
|
7
|
-
@dependencies =
|
6
|
+
@dependencies = Hash.new
|
7
|
+
@removed_dependencies = Set.new
|
8
8
|
end
|
9
9
|
|
10
10
|
def add(name, requirements)
|
11
|
-
@
|
11
|
+
unless @removed_dependencies.include?(name)
|
12
|
+
@dependencies[name] = Dependency.new(name, requirements)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def remove(name)
|
17
|
+
if @removed_dependencies.add?(name)
|
18
|
+
@dependencies.delete(name)
|
19
|
+
end
|
12
20
|
end
|
13
21
|
|
14
22
|
def to_s
|
data/lib/appraisal/gemfile.rb
CHANGED
@@ -2,15 +2,18 @@ require "appraisal/bundler_dsl"
|
|
2
2
|
|
3
3
|
module Appraisal
|
4
4
|
autoload :Gemspec, "appraisal/gemspec"
|
5
|
-
autoload :
|
6
|
-
autoload :PathSource, "appraisal/path_source"
|
5
|
+
autoload :Git, "appraisal/git"
|
7
6
|
autoload :Group, "appraisal/group"
|
7
|
+
autoload :Path, "appraisal/path"
|
8
8
|
autoload :Platform, "appraisal/platform"
|
9
|
+
autoload :Source, "appraisal/source"
|
9
10
|
|
10
11
|
# Load bundler Gemfiles and merge dependencies
|
11
12
|
class Gemfile < BundlerDSL
|
12
13
|
def load(path)
|
13
|
-
|
14
|
+
if File.exist?(path)
|
15
|
+
run(IO.read(path))
|
16
|
+
end
|
14
17
|
end
|
15
18
|
|
16
19
|
def run(definitions)
|
@@ -19,6 +22,7 @@ module Appraisal
|
|
19
22
|
|
20
23
|
def dup
|
21
24
|
Gemfile.new.tap do |gemfile|
|
25
|
+
gemfile.git_sources = @git_sources
|
22
26
|
gemfile.run(for_dup)
|
23
27
|
end
|
24
28
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "appraisal/bundler_dsl"
|
2
|
+
require "appraisal/utils"
|
3
|
+
|
4
|
+
module Appraisal
|
5
|
+
class Source < BundlerDSL
|
6
|
+
def initialize(source)
|
7
|
+
super()
|
8
|
+
@source = source
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
formatted_output indent(super)
|
13
|
+
end
|
14
|
+
|
15
|
+
# :nodoc:
|
16
|
+
def for_dup
|
17
|
+
formatted_output indent(super)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def formatted_output(output_dependencies)
|
23
|
+
<<-OUTPUT.strip
|
24
|
+
source #{@source.inspect} do
|
25
|
+
#{output_dependencies}
|
26
|
+
end
|
27
|
+
OUTPUT
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/appraisal/task.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'appraisal/
|
1
|
+
require 'appraisal/appraisal_file'
|
2
2
|
require 'rake/tasklib'
|
3
3
|
|
4
4
|
module Appraisal
|
@@ -29,7 +29,7 @@ module Appraisal
|
|
29
29
|
end
|
30
30
|
|
31
31
|
begin
|
32
|
-
|
32
|
+
AppraisalFile.each do |appraisal|
|
33
33
|
desc "DEPRECATED: Run the given task for appraisal #{appraisal.name}"
|
34
34
|
task appraisal.name do
|
35
35
|
ARGV.shift
|
@@ -1,10 +1,11 @@
|
|
1
|
-
require "appraisal/
|
1
|
+
require "appraisal/appraisal_file"
|
2
2
|
require "yaml"
|
3
3
|
|
4
4
|
module Appraisal
|
5
5
|
class TravisCIHelper
|
6
|
-
NO_CONFIGURATION_WARNING = <<-WARNING.strip
|
7
|
-
Note: Run
|
6
|
+
NO_CONFIGURATION_WARNING = <<-WARNING.strip.gsub(/\s+/, " ")
|
7
|
+
Note: Run `appraisal generate --travis` to generate Travis CI
|
8
|
+
configuration.
|
8
9
|
WARNING
|
9
10
|
|
10
11
|
INVALID_CONFIGURATION_WARNING = <<-WARNING.strip.gsub(/\s+/, " ")
|
@@ -19,7 +20,7 @@ module Appraisal
|
|
19
20
|
puts "# Put this in your .travis.yml"
|
20
21
|
puts "#{GEMFILES_CONFIGURATION_KEY}:"
|
21
22
|
|
22
|
-
|
23
|
+
AppraisalFile.each do |appraisal|
|
23
24
|
puts " - #{appraisal.relative_gemfile_path}"
|
24
25
|
end
|
25
26
|
end
|
@@ -44,7 +45,7 @@ module Appraisal
|
|
44
45
|
private
|
45
46
|
|
46
47
|
def has_configuration_file?
|
47
|
-
|
48
|
+
File.exist?(CONFIGURATION_FILE)
|
48
49
|
end
|
49
50
|
|
50
51
|
def has_no_gemfiles_configuration?
|
@@ -54,7 +55,7 @@ module Appraisal
|
|
54
55
|
def has_invalid_gemfiles_configuration?
|
55
56
|
if configuration && configuration[GEMFILES_CONFIGURATION_KEY]
|
56
57
|
appraisal_paths =
|
57
|
-
|
58
|
+
AppraisalFile.new.appraisals.map(&:relative_gemfile_path).sort
|
58
59
|
travis_gemfile_paths = configuration[GEMFILES_CONFIGURATION_KEY].sort
|
59
60
|
appraisal_paths != travis_gemfile_paths
|
60
61
|
end
|
data/lib/appraisal/utils.rb
CHANGED
@@ -9,7 +9,7 @@ module Appraisal
|
|
9
9
|
case object
|
10
10
|
when Hash
|
11
11
|
items = object.map do |key, value|
|
12
|
-
|
12
|
+
format_hash_value(key, value)
|
13
13
|
end
|
14
14
|
|
15
15
|
if enclosing_object
|
@@ -22,6 +22,17 @@ module Appraisal
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
def self.format_hash_value(key, value)
|
26
|
+
key = format_string(key, true)
|
27
|
+
value = format_string(value, true)
|
28
|
+
|
29
|
+
if key.start_with?(":")
|
30
|
+
"#{key.sub(/^:/, "")}: #{value}"
|
31
|
+
else
|
32
|
+
"#{key} => #{value}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
25
36
|
def self.format_arguments(arguments)
|
26
37
|
unless arguments.empty?
|
27
38
|
arguments.map { |object| format_string(object, false) }.join(', ')
|
@@ -35,10 +46,17 @@ module Appraisal
|
|
35
46
|
def self.prefix_path(path)
|
36
47
|
if path !~ /^(?:\/|\S:)/ && path !~ /^\S+:\/\// && path !~ /^\S+@\S+:/
|
37
48
|
cleaned_path = path.gsub(/(^|\/)\.(?:\/|$)/, "\\1")
|
38
|
-
|
49
|
+
File.join("..", cleaned_path)
|
39
50
|
else
|
40
51
|
path
|
41
52
|
end
|
42
53
|
end
|
54
|
+
|
55
|
+
def self.bundler_version
|
56
|
+
Gem::Specification.
|
57
|
+
detect { |spec| spec.name == "bundler" }.
|
58
|
+
version.
|
59
|
+
to_s
|
60
|
+
end
|
43
61
|
end
|
44
62
|
end
|
data/lib/appraisal/version.rb
CHANGED
@@ -2,14 +2,17 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe 'Appraisals file Bundler DSL compatibility' do
|
4
4
|
it 'supports all Bundler DSL in Appraisals file' do
|
5
|
-
build_gems %w(bagel orange_juice milk waffle coffee ham
|
6
|
-
|
5
|
+
build_gems %w(bagel orange_juice milk waffle coffee ham
|
6
|
+
sausage pancake rotten_egg)
|
7
|
+
build_git_gems %w(egg croissant pain_au_chocolat omelette)
|
7
8
|
|
8
9
|
build_gemfile <<-Gemfile
|
9
10
|
source 'https://rubygems.org'
|
11
|
+
git_source(:custom_git_source) { |repo| "../gems/\#{repo}" }
|
10
12
|
ruby RUBY_VERSION
|
11
13
|
|
12
14
|
gem 'bagel'
|
15
|
+
gem "croissant", :custom_git_source => "croissant"
|
13
16
|
|
14
17
|
git '../gems/egg' do
|
15
18
|
gem 'egg'
|
@@ -21,6 +24,8 @@ describe 'Appraisals file Bundler DSL compatibility' do
|
|
21
24
|
|
22
25
|
group :breakfast do
|
23
26
|
gem 'orange_juice'
|
27
|
+
gem "omelette", :custom_git_source => "omelette"
|
28
|
+
gem 'rotten_egg'
|
24
29
|
end
|
25
30
|
|
26
31
|
platforms :ruby, :jruby do
|
@@ -31,15 +36,20 @@ describe 'Appraisals file Bundler DSL compatibility' do
|
|
31
36
|
end
|
32
37
|
end
|
33
38
|
|
39
|
+
source "https://other-rubygems.org" do
|
40
|
+
gem "sausage"
|
41
|
+
end
|
42
|
+
|
34
43
|
gem 'appraisal', :path => #{PROJECT_ROOT.inspect}
|
35
44
|
Gemfile
|
36
45
|
|
37
46
|
build_appraisal_file <<-Appraisals
|
38
47
|
appraise 'breakfast' do
|
39
48
|
source 'http://some-other-source.com'
|
40
|
-
ruby "
|
49
|
+
ruby "2.3.0"
|
41
50
|
|
42
51
|
gem 'bread'
|
52
|
+
gem "pain_au_chocolat", :custom_git_source => "pain_au_chocolat"
|
43
53
|
|
44
54
|
git '../gems/egg' do
|
45
55
|
gem 'porched_egg'
|
@@ -50,6 +60,7 @@ describe 'Appraisals file Bundler DSL compatibility' do
|
|
50
60
|
end
|
51
61
|
|
52
62
|
group :breakfast do
|
63
|
+
remove_gem 'rotten_egg'
|
53
64
|
gem 'bacon'
|
54
65
|
|
55
66
|
platforms :rbx do
|
@@ -61,7 +72,12 @@ describe 'Appraisals file Bundler DSL compatibility' do
|
|
61
72
|
gem 'yoghurt'
|
62
73
|
end
|
63
74
|
|
75
|
+
source "https://other-rubygems.org" do
|
76
|
+
gem "pancake"
|
77
|
+
end
|
78
|
+
|
64
79
|
gemspec
|
80
|
+
gemspec :path => "sitepress"
|
65
81
|
end
|
66
82
|
Appraisals
|
67
83
|
|
@@ -74,7 +90,7 @@ describe 'Appraisals file Bundler DSL compatibility' do
|
|
74
90
|
source "https://rubygems.org"
|
75
91
|
source "http://some-other-source.com"
|
76
92
|
|
77
|
-
ruby "
|
93
|
+
ruby "2.3.0"
|
78
94
|
|
79
95
|
git "../../gems/egg" do
|
80
96
|
gem "egg"
|
@@ -87,11 +103,14 @@ describe 'Appraisals file Bundler DSL compatibility' do
|
|
87
103
|
end
|
88
104
|
|
89
105
|
gem "bagel"
|
106
|
+
gem "croissant", :git => "../../gems/croissant"
|
90
107
|
gem "appraisal", :path => #{PROJECT_ROOT.inspect}
|
91
108
|
gem "bread"
|
109
|
+
gem "pain_au_chocolat", :git => "../../gems/pain_au_chocolat"
|
92
110
|
|
93
111
|
group :breakfast do
|
94
112
|
gem "orange_juice"
|
113
|
+
gem "omelette", :git => "../../gems/omelette"
|
95
114
|
gem "bacon"
|
96
115
|
|
97
116
|
platforms :rbx do
|
@@ -108,7 +127,13 @@ describe 'Appraisals file Bundler DSL compatibility' do
|
|
108
127
|
end
|
109
128
|
end
|
110
129
|
|
130
|
+
source "https://other-rubygems.org" do
|
131
|
+
gem "sausage"
|
132
|
+
gem "pancake"
|
133
|
+
end
|
134
|
+
|
111
135
|
gemspec :path => "../"
|
136
|
+
gemspec :path => "../sitepress"
|
112
137
|
Gemfile
|
113
138
|
end
|
114
139
|
end
|
@@ -1,22 +1,53 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe "Bundle with custom path" do
|
4
|
-
|
5
|
-
|
6
|
-
source "https://rubygems.org"
|
4
|
+
let(:gem_name) { 'rack' }
|
5
|
+
let(:path) { 'vendor/bundle' }
|
7
6
|
|
8
|
-
|
9
|
-
Gemfile
|
7
|
+
shared_examples :gemfile_dependencies_are_satisfied do
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
Appraisals
|
9
|
+
it 'installs gems in the --path directory' do
|
10
|
+
build_gemfile <<-Gemfile
|
11
|
+
source "https://rubygems.org"
|
15
12
|
|
16
|
-
|
17
|
-
|
13
|
+
gem 'appraisal', :path => #{PROJECT_ROOT.inspect}
|
14
|
+
Gemfile
|
18
15
|
|
19
|
-
|
20
|
-
|
16
|
+
build_appraisal_file <<-Appraisals
|
17
|
+
appraise "#{gem_name}" do
|
18
|
+
gem '#{gem_name}'
|
19
|
+
end
|
20
|
+
Appraisals
|
21
|
+
|
22
|
+
run %(bundle install --path="#{path}")
|
23
|
+
run 'bundle exec appraisal install'
|
24
|
+
|
25
|
+
installed_gem = Dir.glob("tmp/stage/#{path}/#{Gem.ruby_engine}/*/gems/*").
|
26
|
+
map { |path| path.split('/').last }.
|
27
|
+
select { |gem| gem.include?(gem_name) }
|
28
|
+
expect(installed_gem).not_to be_empty
|
29
|
+
|
30
|
+
bundle_output = run 'bundle check'
|
31
|
+
expect(bundle_output).to include("The Gemfile's dependencies are satisfied")
|
32
|
+
|
33
|
+
appraisal_output = run 'bundle exec appraisal install'
|
34
|
+
expect(appraisal_output).to include("The Gemfile's dependencies are satisfied")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
include_examples :gemfile_dependencies_are_satisfied
|
39
|
+
|
40
|
+
context 'when already installed in vendor/another' do
|
41
|
+
before do
|
42
|
+
build_gemfile <<-Gemfile
|
43
|
+
source "https://rubygems.org"
|
44
|
+
|
45
|
+
gem '#{gem_name}'
|
46
|
+
Gemfile
|
47
|
+
|
48
|
+
run 'bundle install --path vendor/another'
|
49
|
+
end
|
50
|
+
|
51
|
+
include_examples :gemfile_dependencies_are_satisfied
|
21
52
|
end
|
22
53
|
end
|