appraisal2 3.0.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
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +28 -0
- data/CODE_OF_CONDUCT.md +135 -0
- data/CONTRIBUTING.md +136 -0
- data/LICENSE.txt +22 -0
- data/README.md +700 -0
- data/SECURITY.md +21 -0
- data/exe/appraisal +14 -0
- data/lib/appraisal/appraisal.rb +201 -0
- data/lib/appraisal/appraisal_file.rb +52 -0
- data/lib/appraisal/bundler_dsl.rb +209 -0
- data/lib/appraisal/cli.rb +130 -0
- data/lib/appraisal/command.rb +94 -0
- data/lib/appraisal/conditional.rb +32 -0
- data/lib/appraisal/customize.rb +40 -0
- data/lib/appraisal/dependency.rb +51 -0
- data/lib/appraisal/dependency_list.rb +38 -0
- data/lib/appraisal/errors.rb +10 -0
- data/lib/appraisal/gemfile.rb +31 -0
- data/lib/appraisal/gemspec.rb +31 -0
- data/lib/appraisal/git.rb +47 -0
- data/lib/appraisal/group.rb +32 -0
- data/lib/appraisal/ordered_hash.rb +22 -0
- data/lib/appraisal/path.rb +47 -0
- data/lib/appraisal/platform.rb +32 -0
- data/lib/appraisal/source.rb +32 -0
- data/lib/appraisal/task.rb +56 -0
- data/lib/appraisal/utils.rb +71 -0
- data/lib/appraisal/version.rb +5 -0
- data/lib/appraisal.rb +5 -0
- data/lib/appraisal2.rb +6 -0
- data.tar.gz.sig +0 -0
- metadata +268 -0
- metadata.gz.sig +0 -0
data/SECURITY.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Security Policy
|
2
|
+
|
3
|
+
## Supported Versions
|
4
|
+
|
5
|
+
| Version | Supported |
|
6
|
+
|----------|-----------|
|
7
|
+
| 1.latest | ✅ |
|
8
|
+
|
9
|
+
## Security contact information
|
10
|
+
|
11
|
+
To report a security vulnerability, please use the
|
12
|
+
[Tidelift security contact](https://tidelift.com/security).
|
13
|
+
Tidelift will coordinate the fix and disclosure.
|
14
|
+
|
15
|
+
## Additional Support
|
16
|
+
|
17
|
+
If you are interested in support for versions older than the latest release,
|
18
|
+
please consider sponsoring the project / maintainer @ https://liberapay.com/pboling/donate,
|
19
|
+
or find other sponsorship links in the [README].
|
20
|
+
|
21
|
+
[README]: README.md
|
data/exe/appraisal
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "rubygems"
|
5
|
+
require "bundler/setup"
|
6
|
+
require "appraisal2"
|
7
|
+
require "appraisal/cli"
|
8
|
+
|
9
|
+
begin
|
10
|
+
Appraisal::CLI.start
|
11
|
+
rescue Appraisal::AppraisalsNotFound => e
|
12
|
+
puts e.message
|
13
|
+
exit(127)
|
14
|
+
end
|
@@ -0,0 +1,201 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Std Lib
|
4
|
+
require "fileutils"
|
5
|
+
require "pathname"
|
6
|
+
|
7
|
+
# This gem
|
8
|
+
require "appraisal/gemfile"
|
9
|
+
require "appraisal/command"
|
10
|
+
require "appraisal/customize"
|
11
|
+
require "appraisal/utils"
|
12
|
+
|
13
|
+
module Appraisal
|
14
|
+
# Represents one appraisal and its dependencies
|
15
|
+
class Appraisal
|
16
|
+
DEFAULT_INSTALL_OPTIONS = {"jobs" => 1}.freeze
|
17
|
+
|
18
|
+
attr_reader :name, :gemfile
|
19
|
+
|
20
|
+
def initialize(name, source_gemfile)
|
21
|
+
@name = name
|
22
|
+
@gemfile = source_gemfile.dup
|
23
|
+
end
|
24
|
+
|
25
|
+
def eval_gemfile(*args)
|
26
|
+
gemfile.eval_gemfile(*args)
|
27
|
+
end
|
28
|
+
|
29
|
+
def gem(*args)
|
30
|
+
gemfile.gem(*args)
|
31
|
+
end
|
32
|
+
|
33
|
+
def remove_gem(*args)
|
34
|
+
gemfile.remove_gem(*args)
|
35
|
+
end
|
36
|
+
|
37
|
+
def source(*args, &block)
|
38
|
+
gemfile.source(*args, &block)
|
39
|
+
end
|
40
|
+
|
41
|
+
def ruby(*args)
|
42
|
+
gemfile.ruby(*args)
|
43
|
+
end
|
44
|
+
|
45
|
+
def git(*args, &block)
|
46
|
+
gemfile.git(*args, &block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def path(*args, &block)
|
50
|
+
gemfile.path(*args, &block)
|
51
|
+
end
|
52
|
+
|
53
|
+
def group(*args, &block)
|
54
|
+
gemfile.group(*args, &block)
|
55
|
+
end
|
56
|
+
|
57
|
+
def install_if(*args, &block)
|
58
|
+
gemfile.install_if(*args, &block)
|
59
|
+
end
|
60
|
+
|
61
|
+
def platforms(*args, &block)
|
62
|
+
gemfile.platforms(*args, &block)
|
63
|
+
end
|
64
|
+
|
65
|
+
def gemspec(options = {})
|
66
|
+
gemfile.gemspec(options)
|
67
|
+
end
|
68
|
+
|
69
|
+
def git_source(*args, &block)
|
70
|
+
gemfile.git_source(*args, &block)
|
71
|
+
end
|
72
|
+
|
73
|
+
def write_gemfile
|
74
|
+
File.open(gemfile_path, "w") do |file|
|
75
|
+
signature =
|
76
|
+
Customize.heading(self) || "This file was generated by Appraisal2"
|
77
|
+
file.puts([comment_lines(signature), quoted_gemfile].join("\n\n"))
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def install(options = {})
|
82
|
+
commands = [install_command(options).join(" ")]
|
83
|
+
|
84
|
+
commands.unshift(check_command.join(" ")) if options["without"].nil? || options["without"].empty?
|
85
|
+
|
86
|
+
command = commands.join(" || ")
|
87
|
+
|
88
|
+
if Bundler.settings[:path]
|
89
|
+
env = {"BUNDLE_DISABLE_SHARED_GEMS" => "1"}
|
90
|
+
Command.new(command, :env => env).run
|
91
|
+
else
|
92
|
+
Command.new(command).run
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def update(gems = [])
|
97
|
+
Command.new(update_command(gems), :gemfile => gemfile_path).run
|
98
|
+
end
|
99
|
+
|
100
|
+
def gemfile_path
|
101
|
+
gemfile_root.mkdir unless gemfile_root.exist?
|
102
|
+
|
103
|
+
gemfile_root.join(gemfile_name).to_s
|
104
|
+
end
|
105
|
+
|
106
|
+
def relative_gemfile_path
|
107
|
+
File.join("gemfiles", gemfile_name)
|
108
|
+
end
|
109
|
+
|
110
|
+
def relativize
|
111
|
+
current_directory = Pathname.new(Dir.pwd)
|
112
|
+
relative_path = current_directory.relative_path_from(gemfile_root).cleanpath
|
113
|
+
lockfile_content = File.read(lockfile_path)
|
114
|
+
|
115
|
+
File.open(lockfile_path, "w") do |file|
|
116
|
+
file.write(lockfile_content.gsub(
|
117
|
+
/ #{current_directory}/,
|
118
|
+
" #{relative_path}",
|
119
|
+
))
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
def check_command
|
126
|
+
gemfile_option = "--gemfile='#{gemfile_path}'"
|
127
|
+
["bundle", "check", gemfile_option]
|
128
|
+
end
|
129
|
+
|
130
|
+
def install_command(options = {})
|
131
|
+
gemfile_option = "--gemfile='#{gemfile_path}'"
|
132
|
+
["bundle", "install", gemfile_option, bundle_options(options)].compact
|
133
|
+
end
|
134
|
+
|
135
|
+
def update_command(gems)
|
136
|
+
["bundle", "update", *gems].compact
|
137
|
+
end
|
138
|
+
|
139
|
+
def gemfile_root
|
140
|
+
project_root + "gemfiles"
|
141
|
+
end
|
142
|
+
|
143
|
+
def project_root
|
144
|
+
Pathname.new(Dir.pwd)
|
145
|
+
end
|
146
|
+
|
147
|
+
def gemfile_name
|
148
|
+
"#{clean_name}.gemfile"
|
149
|
+
end
|
150
|
+
|
151
|
+
def lockfile_path
|
152
|
+
"#{gemfile_path}.lock"
|
153
|
+
end
|
154
|
+
|
155
|
+
def clean_name
|
156
|
+
name.gsub(/[^\w.]/, "_")
|
157
|
+
end
|
158
|
+
|
159
|
+
def bundle_options(options)
|
160
|
+
full_options = DEFAULT_INSTALL_OPTIONS.dup.merge(options)
|
161
|
+
options_strings = []
|
162
|
+
jobs = full_options.delete("jobs")
|
163
|
+
if jobs > 1
|
164
|
+
if Utils.support_parallel_installation?
|
165
|
+
options_strings << "--jobs=#{jobs}"
|
166
|
+
else
|
167
|
+
warn("Your current version of Bundler does not support parallel installation. Please " \
|
168
|
+
"upgrade Bundler to version >= 1.4.0, or invoke `appraisal` without `--jobs` option.")
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
path = full_options.delete("path")
|
173
|
+
if path
|
174
|
+
relative_path = project_root.join(options["path"])
|
175
|
+
options_strings << "--path #{relative_path}"
|
176
|
+
end
|
177
|
+
|
178
|
+
full_options.each do |flag, val|
|
179
|
+
options_strings << "--#{flag} #{val}"
|
180
|
+
end
|
181
|
+
|
182
|
+
options_strings.join(" ") if options_strings != []
|
183
|
+
end
|
184
|
+
|
185
|
+
def comment_lines(heading)
|
186
|
+
heading.lines.map do |line|
|
187
|
+
if line.lstrip.empty?
|
188
|
+
line
|
189
|
+
else
|
190
|
+
"# #{line}"
|
191
|
+
end
|
192
|
+
end.join
|
193
|
+
end
|
194
|
+
|
195
|
+
def quoted_gemfile
|
196
|
+
return gemfile.to_s unless Customize.single_quotes
|
197
|
+
|
198
|
+
gemfile.to_s.tr('"', "'")
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "appraisal/appraisal"
|
4
|
+
require "appraisal/customize"
|
5
|
+
require "appraisal/errors"
|
6
|
+
require "appraisal/gemfile"
|
7
|
+
|
8
|
+
module Appraisal
|
9
|
+
# Loads and parses Appraisals file
|
10
|
+
class AppraisalFile
|
11
|
+
attr_reader :appraisals, :gemfile
|
12
|
+
|
13
|
+
def self.each(&block)
|
14
|
+
new.each(&block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@appraisals = []
|
19
|
+
@gemfile = Gemfile.new
|
20
|
+
@gemfile.load(ENV["BUNDLE_GEMFILE"] || "Gemfile")
|
21
|
+
|
22
|
+
raise AppraisalsNotFound unless File.exist?(path)
|
23
|
+
|
24
|
+
run(File.read(path))
|
25
|
+
end
|
26
|
+
|
27
|
+
def each(&block)
|
28
|
+
appraisals.each(&block)
|
29
|
+
end
|
30
|
+
|
31
|
+
def appraise(name, &block)
|
32
|
+
appraisal = Appraisal.new(name, gemfile)
|
33
|
+
appraisal.instance_eval(&block)
|
34
|
+
@appraisals << appraisal
|
35
|
+
end
|
36
|
+
|
37
|
+
def customize_gemfiles(&_block)
|
38
|
+
args = yield
|
39
|
+
Customize.new(args)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def run(definitions)
|
45
|
+
instance_eval(definitions, __FILE__, __LINE__)
|
46
|
+
end
|
47
|
+
|
48
|
+
def path
|
49
|
+
"Appraisals"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,209 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "appraisal/dependency_list"
|
4
|
+
require "appraisal/ordered_hash"
|
5
|
+
|
6
|
+
module Appraisal
|
7
|
+
class BundlerDSL
|
8
|
+
attr_reader :dependencies
|
9
|
+
|
10
|
+
PARTS = %w[
|
11
|
+
source
|
12
|
+
ruby_version
|
13
|
+
gits
|
14
|
+
paths
|
15
|
+
dependencies
|
16
|
+
groups
|
17
|
+
platforms
|
18
|
+
source_blocks
|
19
|
+
install_if
|
20
|
+
gemspec
|
21
|
+
eval_gemfile
|
22
|
+
]
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
@sources = []
|
26
|
+
@ruby_version = nil
|
27
|
+
@dependencies = DependencyList.new
|
28
|
+
@gemspecs = []
|
29
|
+
@groups = OrderedHash.new
|
30
|
+
@platforms = OrderedHash.new
|
31
|
+
@gits = OrderedHash.new
|
32
|
+
@paths = OrderedHash.new
|
33
|
+
@source_blocks = OrderedHash.new
|
34
|
+
@git_sources = {}
|
35
|
+
@install_if = {}
|
36
|
+
@eval_gemfile = []
|
37
|
+
end
|
38
|
+
|
39
|
+
def run(&block)
|
40
|
+
instance_exec(&block)
|
41
|
+
end
|
42
|
+
|
43
|
+
def eval_gemfile(path, contents = nil)
|
44
|
+
@eval_gemfile << [path, contents]
|
45
|
+
end
|
46
|
+
|
47
|
+
def gem(name, *requirements)
|
48
|
+
@dependencies.add(name, substitute_git_source(requirements))
|
49
|
+
end
|
50
|
+
|
51
|
+
def remove_gem(name)
|
52
|
+
@dependencies.remove(name)
|
53
|
+
end
|
54
|
+
|
55
|
+
def group(*names, &block)
|
56
|
+
@groups[names] ||=
|
57
|
+
Group.new(names).tap { |g| g.git_sources = @git_sources.dup }
|
58
|
+
@groups[names].run(&block)
|
59
|
+
end
|
60
|
+
|
61
|
+
def install_if(condition, &block)
|
62
|
+
@install_if[condition] ||=
|
63
|
+
Conditional.new(condition).tap { |g| g.git_sources = @git_sources.dup }
|
64
|
+
@install_if[condition].run(&block)
|
65
|
+
end
|
66
|
+
|
67
|
+
def platforms(*names, &block)
|
68
|
+
@platforms[names] ||=
|
69
|
+
Platform.new(names).tap { |g| g.git_sources = @git_sources.dup }
|
70
|
+
@platforms[names].run(&block)
|
71
|
+
end
|
72
|
+
|
73
|
+
alias_method :platform, :platforms
|
74
|
+
|
75
|
+
def source(source, &block)
|
76
|
+
if block_given?
|
77
|
+
@source_blocks[source] ||=
|
78
|
+
Source.new(source).tap { |g| g.git_sources = @git_sources.dup }
|
79
|
+
@source_blocks[source].run(&block)
|
80
|
+
else
|
81
|
+
@sources << source
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def ruby(ruby_version)
|
86
|
+
@ruby_version = ruby_version
|
87
|
+
end
|
88
|
+
|
89
|
+
def git(source, options = {}, &block)
|
90
|
+
@gits[source] ||=
|
91
|
+
Git.new(source, options).tap { |g| g.git_sources = @git_sources.dup }
|
92
|
+
@gits[source].run(&block)
|
93
|
+
end
|
94
|
+
|
95
|
+
def path(source, options = {}, &block)
|
96
|
+
@paths[source] ||=
|
97
|
+
Path.new(source, options).tap { |g| g.git_sources = @git_sources.dup }
|
98
|
+
@paths[source].run(&block)
|
99
|
+
end
|
100
|
+
|
101
|
+
def to_s
|
102
|
+
Utils.join_parts(PARTS.map { |part| send(:"#{part}_entry") })
|
103
|
+
end
|
104
|
+
|
105
|
+
def for_dup
|
106
|
+
Utils.join_parts(PARTS.map { |part| send(:"#{part}_entry_for_dup") })
|
107
|
+
end
|
108
|
+
|
109
|
+
def gemspec(options = {})
|
110
|
+
@gemspecs << Gemspec.new(options)
|
111
|
+
end
|
112
|
+
|
113
|
+
def git_source(source, &block)
|
114
|
+
@git_sources[source] = block
|
115
|
+
end
|
116
|
+
|
117
|
+
protected
|
118
|
+
|
119
|
+
attr_writer :git_sources
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
def eval_gemfile_entry
|
124
|
+
@eval_gemfile.map { |(p, c)| "eval_gemfile(#{p.inspect}#{", #{c.inspect}" if c})" } * "\n\n"
|
125
|
+
end
|
126
|
+
|
127
|
+
alias_method :eval_gemfile_entry_for_dup, :eval_gemfile_entry
|
128
|
+
|
129
|
+
def source_entry
|
130
|
+
@sources.uniq.map { |source| "source #{source.inspect}" }.join("\n")
|
131
|
+
end
|
132
|
+
|
133
|
+
alias_method :source_entry_for_dup, :source_entry
|
134
|
+
|
135
|
+
def ruby_version_entry
|
136
|
+
return unless @ruby_version
|
137
|
+
|
138
|
+
case @ruby_version
|
139
|
+
when String then "ruby #{@ruby_version.inspect}"
|
140
|
+
else "ruby(#{Utils.format_string(@ruby_version)})"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
alias_method :ruby_version_entry_for_dup, :ruby_version_entry
|
145
|
+
|
146
|
+
def gemspec_entry
|
147
|
+
@gemspecs.map(&:to_s).join("\n")
|
148
|
+
end
|
149
|
+
|
150
|
+
def gemspec_entry_for_dup
|
151
|
+
@gemspecs.map(&:for_dup).join("\n")
|
152
|
+
end
|
153
|
+
|
154
|
+
def dependencies_entry
|
155
|
+
@dependencies.to_s
|
156
|
+
end
|
157
|
+
|
158
|
+
def dependencies_entry_for_dup
|
159
|
+
@dependencies.for_dup
|
160
|
+
end
|
161
|
+
|
162
|
+
[:gits, :paths, :platforms, :groups, :source_blocks, :install_if].each do |method_name|
|
163
|
+
class_eval <<-METHODS, __FILE__, __LINE__ + 1
|
164
|
+
private
|
165
|
+
|
166
|
+
def #{method_name}_entry
|
167
|
+
@#{method_name}.values.map(&:to_s).join("\n\n")
|
168
|
+
end
|
169
|
+
|
170
|
+
def #{method_name}_entry_for_dup
|
171
|
+
@#{method_name}.values.map(&:for_dup).join("\n\n")
|
172
|
+
end
|
173
|
+
METHODS
|
174
|
+
end
|
175
|
+
|
176
|
+
def indent(string)
|
177
|
+
indent_by = ENV.fetch("APPRAISAL_INDENTER", "lookaround")
|
178
|
+
if indent_by == "lookaround"
|
179
|
+
# Default indenter for Appraisal v3
|
180
|
+
# Uses a "look-around" of the "look-behind" variety to indent lines that are more than just empty space.
|
181
|
+
# In other words, retain existing indentation, and indent the line again, but not on empty lines.
|
182
|
+
string.
|
183
|
+
# NOTES:
|
184
|
+
# (?![\r\n]) - Negative Look Behind which requires that the following pattern,
|
185
|
+
# which is (\s*) in this case, *not* be followed by a new line character
|
186
|
+
# (\s*) - Captures whitespace at beginning of the line
|
187
|
+
# Learn more here: https://learnbyexample.github.io/Ruby_Regexp/lookarounds.html
|
188
|
+
gsub(/^(?![\r\n])(\s*)/, ' \0').
|
189
|
+
rstrip
|
190
|
+
elsif indent_by == "capture"
|
191
|
+
# Original indentation regex for Appraisal < v3
|
192
|
+
string.gsub(/^(.+)$/, ' \1').rstrip
|
193
|
+
else
|
194
|
+
string
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def substitute_git_source(requirements)
|
199
|
+
requirements.each do |requirement|
|
200
|
+
next unless requirement.is_a?(Hash)
|
201
|
+
|
202
|
+
(requirement.keys & @git_sources.keys).each do |matching_source|
|
203
|
+
value = requirement.delete(matching_source)
|
204
|
+
requirement[:git] = @git_sources[matching_source].call(value)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "thor"
|
4
|
+
require "fileutils"
|
5
|
+
|
6
|
+
module Appraisal
|
7
|
+
class CLI < Thor
|
8
|
+
default_task :install
|
9
|
+
map ["-v", "--version"] => "version"
|
10
|
+
|
11
|
+
class << self
|
12
|
+
# Override help command to print out usage
|
13
|
+
def help(shell, subcommand = false)
|
14
|
+
shell.say(strip_heredoc(<<-HELP))
|
15
|
+
Appraisal: Find out what your Ruby gems are worth.
|
16
|
+
|
17
|
+
Usage:
|
18
|
+
appraisal [APPRAISAL_NAME] EXTERNAL_COMMAND
|
19
|
+
|
20
|
+
If APPRAISAL_NAME is given, only run that EXTERNAL_COMMAND against the given
|
21
|
+
appraisal, otherwise it runs the EXTERNAL_COMMAND against all appraisals.
|
22
|
+
HELP
|
23
|
+
|
24
|
+
if File.exist?("Appraisals")
|
25
|
+
shell.say
|
26
|
+
shell.say("Available Appraisal(s):")
|
27
|
+
|
28
|
+
AppraisalFile.each do |appraisal|
|
29
|
+
shell.say(" - #{appraisal.name}")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
shell.say
|
34
|
+
|
35
|
+
super
|
36
|
+
end
|
37
|
+
|
38
|
+
def exit_on_failure?
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def strip_heredoc(string)
|
45
|
+
indent = string.scan(/^[ \t]*(?=\S)/).min.size || 0
|
46
|
+
string.gsub(/^[ \t]{#{indent}}/, "")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
desc "install", "Resolve and install dependencies for each appraisal"
|
51
|
+
method_option "jobs",
|
52
|
+
:aliases => "j",
|
53
|
+
:type => :numeric,
|
54
|
+
:default => 1,
|
55
|
+
:banner => "SIZE",
|
56
|
+
:desc => "Install gems in parallel using the given number of workers."
|
57
|
+
method_option "retry",
|
58
|
+
:type => :numeric,
|
59
|
+
:default => 1,
|
60
|
+
:desc => "Retry network and git requests that have failed"
|
61
|
+
method_option "without",
|
62
|
+
:banner => "GROUP_NAMES",
|
63
|
+
:desc => "A space-separated list of groups referencing gems to skip " \
|
64
|
+
"during installation. Bundler will remember this option."
|
65
|
+
method_option "full-index",
|
66
|
+
:type => :boolean,
|
67
|
+
:desc => "Run bundle install with the " \
|
68
|
+
"full-index argument."
|
69
|
+
method_option "path",
|
70
|
+
:type => :string,
|
71
|
+
:desc => "Install gems in the specified directory. " \
|
72
|
+
"Bundler will remember this option."
|
73
|
+
|
74
|
+
def install
|
75
|
+
invoke(:generate, [], {})
|
76
|
+
|
77
|
+
AppraisalFile.each do |appraisal|
|
78
|
+
appraisal.install(options)
|
79
|
+
appraisal.relativize
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
desc "generate", "Generate a gemfile for each appraisal"
|
84
|
+
def generate
|
85
|
+
AppraisalFile.each do |appraisal|
|
86
|
+
appraisal.write_gemfile
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
desc "clean", "Remove all generated gemfiles and lockfiles from gemfiles folder"
|
91
|
+
def clean
|
92
|
+
FileUtils.rm_f(Dir["gemfiles/*.{gemfile,gemfile.lock}"])
|
93
|
+
end
|
94
|
+
|
95
|
+
desc "update [LIST_OF_GEMS]", "Remove all generated gemfiles and lockfiles, resolve, and install dependencies again"
|
96
|
+
def update(*gems)
|
97
|
+
invoke(:generate, [])
|
98
|
+
|
99
|
+
AppraisalFile.each do |appraisal|
|
100
|
+
appraisal.update(gems)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
desc "list", "List the names of the defined appraisals"
|
105
|
+
def list
|
106
|
+
AppraisalFile.new.appraisals.each { |appraisal| puts appraisal.name }
|
107
|
+
end
|
108
|
+
|
109
|
+
desc "version", "Display the version and exit"
|
110
|
+
def version
|
111
|
+
puts "Appraisal2 #{VERSION}"
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def method_missing(name, *args)
|
117
|
+
matching_appraisal = AppraisalFile.new.appraisals.detect do |appraisal|
|
118
|
+
appraisal.name == name.to_s
|
119
|
+
end
|
120
|
+
|
121
|
+
if matching_appraisal
|
122
|
+
Command.new(args, :gemfile => matching_appraisal.gemfile_path).run
|
123
|
+
else
|
124
|
+
AppraisalFile.each do |appraisal|
|
125
|
+
Command.new(ARGV, :gemfile => appraisal.gemfile_path).run
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|