bundler 1.13.0.rc.1 → 1.13.0.rc.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of bundler might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.codeclimate.yml +1 -0
- data/.rubocop.yml +8 -0
- data/.rubocop_todo.yml +21 -21
- data/.travis.yml +5 -1
- data/CHANGELOG.md +33 -1
- data/DEVELOPMENT.md +1 -1
- data/Rakefile +21 -12
- data/bin/rake +1 -1
- data/bin/rspec +1 -1
- data/bin/rubocop +2 -2
- data/bundler.gemspec +2 -2
- data/exe/bundler +1 -19
- data/lib/bundler.rb +43 -34
- data/lib/bundler/cli.rb +54 -5
- data/lib/bundler/cli/binstubs.rb +3 -2
- data/lib/bundler/cli/console.rb +3 -0
- data/lib/bundler/cli/doctor.rb +95 -0
- data/lib/bundler/cli/exec.rb +18 -2
- data/lib/bundler/cli/gem.rb +1 -1
- data/lib/bundler/cli/inject.rb +25 -7
- data/lib/bundler/cli/install.rb +23 -2
- data/lib/bundler/cli/lock.rb +14 -2
- data/lib/bundler/cli/update.rb +9 -0
- data/lib/bundler/definition.rb +86 -17
- data/lib/bundler/deployment.rb +6 -0
- data/lib/bundler/dsl.rb +67 -22
- data/lib/bundler/env.rb +1 -1
- data/lib/bundler/environment_preserver.rb +1 -1
- data/lib/bundler/errors.rb +11 -1
- data/lib/bundler/fetcher.rb +3 -2
- data/lib/bundler/fetcher/base.rb +10 -0
- data/lib/bundler/fetcher/compact_index.rb +27 -9
- data/lib/bundler/fetcher/dependency.rb +1 -12
- data/lib/bundler/fetcher/downloader.rb +1 -1
- data/lib/bundler/friendly_errors.rb +4 -2
- data/lib/bundler/gem_helper.rb +2 -2
- data/lib/bundler/gem_version_promoter.rb +175 -0
- data/lib/bundler/graph.rb +4 -25
- data/lib/bundler/index.rb +9 -1
- data/lib/bundler/injector.rb +12 -5
- data/lib/bundler/inline.rb +2 -2
- data/lib/bundler/installer.rb +23 -8
- data/lib/bundler/installer/gem_installer.rb +13 -15
- data/lib/bundler/installer/parallel_installer.rb +121 -99
- data/lib/bundler/lazy_specification.rb +8 -2
- data/lib/bundler/lockfile_parser.rb +20 -12
- data/lib/bundler/mirror.rb +2 -2
- data/lib/bundler/plugin.rb +153 -31
- data/lib/bundler/plugin/api.rb +29 -5
- data/lib/bundler/plugin/api/source.rb +293 -0
- data/lib/bundler/plugin/dsl.rb +25 -1
- data/lib/bundler/plugin/index.rb +80 -13
- data/lib/bundler/plugin/installer.rb +6 -10
- data/lib/bundler/plugin/source_list.rb +4 -0
- data/lib/bundler/postit_trampoline.rb +57 -40
- data/lib/bundler/resolver.rb +24 -12
- data/lib/bundler/retry.rb +2 -1
- data/lib/bundler/ruby_version.rb +4 -2
- data/lib/bundler/rubygems_ext.rb +10 -3
- data/lib/bundler/rubygems_gem_installer.rb +6 -0
- data/lib/bundler/rubygems_integration.rb +101 -66
- data/lib/bundler/runtime.rb +25 -2
- data/lib/bundler/settings.rb +30 -11
- data/lib/bundler/setup.rb +6 -3
- data/lib/bundler/shared_helpers.rb +11 -5
- data/lib/bundler/source/gemspec.rb +4 -0
- data/lib/bundler/source/git.rb +9 -6
- data/lib/bundler/source/git/git_proxy.rb +27 -3
- data/lib/bundler/source/path.rb +4 -26
- data/lib/bundler/source/path/installer.rb +39 -11
- data/lib/bundler/source/rubygems.rb +1 -1
- data/lib/bundler/source_list.rb +28 -8
- data/lib/bundler/spec_set.rb +1 -1
- data/lib/bundler/templates/Executable.standalone +4 -2
- data/lib/bundler/templates/Gemfile +0 -1
- data/lib/bundler/ui/shell.rb +11 -3
- data/lib/bundler/ui/silent.rb +1 -3
- data/lib/bundler/vendor/compact_index_client/lib/compact_index_client.rb +1 -2
- data/lib/bundler/vendor/compact_index_client/lib/compact_index_client/cache.rb +16 -2
- data/lib/bundler/version.rb +1 -1
- data/lib/bundler/yaml_serializer.rb +34 -11
- data/man/bundle-binstubs.ronn +29 -0
- data/man/bundle-config.ronn +32 -0
- data/man/bundle-install.ronn +6 -41
- data/man/bundle-package.ronn +1 -1
- data/man/bundle.ronn +4 -3
- data/man/gemfile.5.ronn +1 -1
- metadata +13 -9
- data/lib/bundler/environment.rb +0 -42
data/lib/bundler/fetcher/base.rb
CHANGED
@@ -36,7 +36,7 @@ module Bundler
|
|
36
36
|
remaining_gems = gem_names.dup
|
37
37
|
|
38
38
|
until remaining_gems.empty?
|
39
|
-
|
39
|
+
log_specs "Looking up gems #{remaining_gems.inspect}"
|
40
40
|
|
41
41
|
deps = compact_index_client.dependencies(remaining_gems)
|
42
42
|
next_gems = deps.map {|d| d[3].map(&:first).flatten(1) }.flatten(1).uniq
|
@@ -44,6 +44,8 @@ module Bundler
|
|
44
44
|
complete_gems.concat(deps.map(&:first)).uniq!
|
45
45
|
remaining_gems = next_gems - complete_gems
|
46
46
|
end
|
47
|
+
@bundle_worker.stop if @bundle_worker
|
48
|
+
@bundle_worker = nil # reset it. Not sure if necessary
|
47
49
|
|
48
50
|
gem_info
|
49
51
|
end
|
@@ -76,28 +78,44 @@ module Bundler
|
|
76
78
|
private
|
77
79
|
|
78
80
|
def compact_index_client
|
79
|
-
@compact_index_client ||=
|
80
|
-
compact_fetcher = lambda do |path, headers|
|
81
|
-
downloader.fetch(fetch_uri + path, headers)
|
82
|
-
end
|
83
|
-
|
81
|
+
@compact_index_client ||=
|
84
82
|
SharedHelpers.filesystem_access(cache_path) do
|
85
83
|
CompactIndexClient.new(cache_path, compact_fetcher)
|
86
84
|
end.tap do |client|
|
87
85
|
client.in_parallel = lambda do |inputs, &blk|
|
88
86
|
func = lambda {|object, _index| blk.call(object) }
|
89
|
-
|
90
|
-
worker = Bundler::Worker.new(25, worker_name, func)
|
87
|
+
worker = bundle_worker(func)
|
91
88
|
inputs.each {|input| worker.enq(input) }
|
92
|
-
inputs.map { worker.deq }
|
89
|
+
inputs.map { worker.deq }
|
93
90
|
end
|
94
91
|
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def bundle_worker(func = nil)
|
95
|
+
@bundle_worker ||= begin
|
96
|
+
worker_name = "Compact Index (#{display_uri.host})"
|
97
|
+
Bundler::Worker.new(25, worker_name, func)
|
98
|
+
end
|
99
|
+
@bundle_worker.tap do |worker|
|
100
|
+
worker.instance_variable_set(:@func, func) if func
|
95
101
|
end
|
96
102
|
end
|
97
103
|
|
98
104
|
def cache_path
|
99
105
|
Bundler.user_cache.join("compact_index", remote.cache_slug)
|
100
106
|
end
|
107
|
+
|
108
|
+
def compact_fetcher
|
109
|
+
lambda do |path, headers|
|
110
|
+
begin
|
111
|
+
downloader.fetch(fetch_uri + path, headers)
|
112
|
+
rescue NetworkDownError => e
|
113
|
+
raise unless Bundler.settings[:allow_offline_install] && headers["If-None-Match"]
|
114
|
+
Bundler.ui.warn "Using the cached data for the new index because of a network error: #{e}"
|
115
|
+
Net::HTTPNotModified.new(nil, nil, nil)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
101
119
|
end
|
102
120
|
end
|
103
121
|
end
|
@@ -23,7 +23,7 @@ module Bundler
|
|
23
23
|
def specs(gem_names, full_dependency_list = [], last_spec_list = [])
|
24
24
|
query_list = gem_names.uniq - full_dependency_list
|
25
25
|
|
26
|
-
log_specs
|
26
|
+
log_specs "Query List: #{query_list.inspect}"
|
27
27
|
|
28
28
|
return last_spec_list if query_list.empty?
|
29
29
|
|
@@ -76,17 +76,6 @@ module Bundler
|
|
76
76
|
uri.query = "gems=#{CGI.escape(gem_names.join(","))}" if gem_names.any?
|
77
77
|
uri
|
78
78
|
end
|
79
|
-
|
80
|
-
private
|
81
|
-
|
82
|
-
def log_specs(query_list)
|
83
|
-
# only display the message on the first run
|
84
|
-
if Bundler.ui.debug?
|
85
|
-
Bundler.ui.debug "Query List: #{query_list.inspect}"
|
86
|
-
else
|
87
|
-
Bundler.ui.info ".", false
|
88
|
-
end
|
89
|
-
end
|
90
79
|
end
|
91
80
|
end
|
92
81
|
end
|
@@ -14,7 +14,7 @@ module Bundler
|
|
14
14
|
raise HTTPError, "Too many redirects" if counter >= redirect_limit
|
15
15
|
|
16
16
|
response = request(uri, options)
|
17
|
-
Bundler.ui.debug("HTTP #{response.code} #{response.message}")
|
17
|
+
Bundler.ui.debug("HTTP #{response.code} #{response.message} #{uri}")
|
18
18
|
|
19
19
|
case response
|
20
20
|
when Net::HTTPSuccess, Net::HTTPNotModified
|
@@ -12,7 +12,7 @@ module Bundler
|
|
12
12
|
when YamlSyntaxError
|
13
13
|
Bundler.ui.error error.message
|
14
14
|
Bundler.ui.trace error.orig_exception
|
15
|
-
when Dsl::DSLError
|
15
|
+
when Dsl::DSLError, GemspecError
|
16
16
|
Bundler.ui.error error.message
|
17
17
|
when GemRequireError
|
18
18
|
Bundler.ui.error error.message
|
@@ -89,8 +89,10 @@ module Bundler
|
|
89
89
|
end
|
90
90
|
|
91
91
|
def issues_url(exception)
|
92
|
+
message = exception.message.lines.first.tr(":", " ").chomp
|
93
|
+
message = message.split("-").first if exception.is_a?(Errno)
|
92
94
|
"https://github.com/bundler/bundler/search?q=" \
|
93
|
-
"#{CGI.escape(
|
95
|
+
"#{CGI.escape(message)}&type=Issues"
|
94
96
|
end
|
95
97
|
end
|
96
98
|
|
data/lib/bundler/gem_helper.rb
CHANGED
@@ -140,7 +140,7 @@ module Bundler
|
|
140
140
|
end
|
141
141
|
|
142
142
|
def tag_version
|
143
|
-
sh "git tag -
|
143
|
+
sh "git tag -m \"Version #{version}\" #{version_tag}"
|
144
144
|
Bundler.ui.confirm "Tagged #{version_tag}."
|
145
145
|
yield if block_given?
|
146
146
|
rescue
|
@@ -182,7 +182,7 @@ module Bundler
|
|
182
182
|
end
|
183
183
|
|
184
184
|
def gem_push?
|
185
|
-
|
185
|
+
!%w(n no nil false off 0).include?(ENV["gem_push"].to_s.downcase)
|
186
186
|
end
|
187
187
|
end
|
188
188
|
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Bundler
|
3
|
+
# This class contains all of the logic for determining the next version of a
|
4
|
+
# Gem to update to based on the requested level (patch, minor, major).
|
5
|
+
# Primarily designed to work with Resolver which will provide it the list of
|
6
|
+
# available dependency versions as found in its index, before returning it to
|
7
|
+
# to the resolution engine to select the best version.
|
8
|
+
class GemVersionPromoter
|
9
|
+
attr_reader :level, :locked_specs, :unlock_gems
|
10
|
+
|
11
|
+
# By default, strict is false, meaning every available version of a gem
|
12
|
+
# is returned from sort_versions. The order gives preference to the
|
13
|
+
# requested level (:patch, :minor, :major) but in complicated requirement
|
14
|
+
# cases some gems will by necessity by promoted past the requested level,
|
15
|
+
# or even reverted to older versions.
|
16
|
+
#
|
17
|
+
# If strict is set to true, the results from sort_versions will be
|
18
|
+
# truncated, eliminating any version outside the current level scope.
|
19
|
+
# This can lead to unexpected outcomes or even VersionConflict exceptions
|
20
|
+
# that report a version of a gem not existing for versions that indeed do
|
21
|
+
# existing in the referenced source.
|
22
|
+
attr_accessor :strict
|
23
|
+
|
24
|
+
# Given a list of locked_specs and a list of gems to unlock creates a
|
25
|
+
# GemVersionPromoter instance.
|
26
|
+
#
|
27
|
+
# @param locked_specs [SpecSet] All current locked specs. Unlike Definition
|
28
|
+
# where this list is empty if all gems are being updated, this should
|
29
|
+
# always be populated for all gems so this class can properly function.
|
30
|
+
# @param unlock_gems [String] List of gem names being unlocked. If empty,
|
31
|
+
# all gems will be considered unlocked.
|
32
|
+
# @return [GemVersionPromoter]
|
33
|
+
def initialize(locked_specs = SpecSet.new([]), unlock_gems = [])
|
34
|
+
@level = :major
|
35
|
+
@strict = false
|
36
|
+
@locked_specs = locked_specs
|
37
|
+
@unlock_gems = unlock_gems
|
38
|
+
@sort_versions = {}
|
39
|
+
end
|
40
|
+
|
41
|
+
# @param value [Symbol] One of three Symbols: :major, :minor or :patch.
|
42
|
+
def level=(value)
|
43
|
+
v = case value
|
44
|
+
when String, Symbol
|
45
|
+
value.to_sym
|
46
|
+
end
|
47
|
+
|
48
|
+
raise ArgumentError, "Unexpected level #{v}. Must be :major, :minor or :patch" unless [:major, :minor, :patch].include?(v)
|
49
|
+
@level = v
|
50
|
+
end
|
51
|
+
|
52
|
+
# Given a Dependency and an Array of SpecGroups of available versions for a
|
53
|
+
# gem, this method will return the Array of SpecGroups sorted (and possibly
|
54
|
+
# truncated if strict is true) in an order to give preference to the current
|
55
|
+
# level (:major, :minor or :patch) when resolution is deciding what versions
|
56
|
+
# best resolve all dependencies in the bundle.
|
57
|
+
# @param dep [Dependency] The Dependency of the gem.
|
58
|
+
# @param spec_groups [SpecGroup] An array of SpecGroups for the same gem
|
59
|
+
# named in the @dep param.
|
60
|
+
# @return [SpecGroup] A new instance of the SpecGroup Array sorted and
|
61
|
+
# possibly filtered.
|
62
|
+
def sort_versions(dep, spec_groups)
|
63
|
+
before_result = "before sort_versions: #{debug_format_result(dep, spec_groups).inspect}" if ENV["DEBUG_RESOLVER"]
|
64
|
+
|
65
|
+
@sort_versions[dep] ||= begin
|
66
|
+
gem_name = dep.name
|
67
|
+
|
68
|
+
# An Array per version returned, different entries for different platforms.
|
69
|
+
# We only need the version here so it's ok to hard code this to the first instance.
|
70
|
+
locked_spec = locked_specs[gem_name].first
|
71
|
+
|
72
|
+
if strict
|
73
|
+
filter_dep_specs(spec_groups, locked_spec)
|
74
|
+
else
|
75
|
+
sort_dep_specs(spec_groups, locked_spec)
|
76
|
+
end.tap do |specs|
|
77
|
+
if ENV["DEBUG_RESOLVER"]
|
78
|
+
STDERR.puts before_result
|
79
|
+
STDERR.puts " after sort_versions: #{debug_format_result(dep, specs).inspect}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# @return [bool] Convenience method for testing value of level variable.
|
86
|
+
def major?
|
87
|
+
level == :major
|
88
|
+
end
|
89
|
+
|
90
|
+
# @return [bool] Convenience method for testing value of level variable.
|
91
|
+
def minor?
|
92
|
+
level == :minor
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def filter_dep_specs(spec_groups, locked_spec)
|
98
|
+
res = spec_groups.select do |spec_group|
|
99
|
+
if locked_spec && !major?
|
100
|
+
gsv = spec_group.version
|
101
|
+
lsv = locked_spec.version
|
102
|
+
|
103
|
+
must_match = minor? ? [0] : [0, 1]
|
104
|
+
|
105
|
+
matches = must_match.map {|idx| gsv.segments[idx] == lsv.segments[idx] }
|
106
|
+
(matches.uniq == [true]) ? (gsv >= lsv) : false
|
107
|
+
else
|
108
|
+
true
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
sort_dep_specs(res, locked_spec)
|
113
|
+
end
|
114
|
+
|
115
|
+
def sort_dep_specs(spec_groups, locked_spec)
|
116
|
+
return spec_groups unless locked_spec
|
117
|
+
@gem_name = locked_spec.name
|
118
|
+
@locked_version = locked_spec.version
|
119
|
+
|
120
|
+
result = spec_groups.sort do |a, b|
|
121
|
+
@a_ver = a.version
|
122
|
+
@b_ver = b.version
|
123
|
+
if major?
|
124
|
+
@a_ver <=> @b_ver
|
125
|
+
elsif either_version_older_than_locked
|
126
|
+
@a_ver <=> @b_ver
|
127
|
+
elsif segments_do_not_match(:major)
|
128
|
+
@b_ver <=> @a_ver
|
129
|
+
elsif !minor? && segments_do_not_match(:minor)
|
130
|
+
@b_ver <=> @a_ver
|
131
|
+
else
|
132
|
+
@a_ver <=> @b_ver
|
133
|
+
end
|
134
|
+
end
|
135
|
+
post_sort(result)
|
136
|
+
end
|
137
|
+
|
138
|
+
def either_version_older_than_locked
|
139
|
+
@a_ver < @locked_version || @b_ver < @locked_version
|
140
|
+
end
|
141
|
+
|
142
|
+
def segments_do_not_match(level)
|
143
|
+
index = [:major, :minor].index(level)
|
144
|
+
@a_ver.segments[index] != @b_ver.segments[index]
|
145
|
+
end
|
146
|
+
|
147
|
+
def unlocking_gem?
|
148
|
+
unlock_gems.empty? || unlock_gems.include?(@gem_name)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Specific version moves can't always reliably be done during sorting
|
152
|
+
# as not all elements are compared against each other.
|
153
|
+
def post_sort(result)
|
154
|
+
# default :major behavior in Bundler does not do this
|
155
|
+
return result if major?
|
156
|
+
if unlocking_gem?
|
157
|
+
result
|
158
|
+
else
|
159
|
+
move_version_to_end(result, @locked_version)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def move_version_to_end(result, version)
|
164
|
+
move, keep = result.partition {|s| s.version.to_s == version.to_s }
|
165
|
+
keep.concat(move)
|
166
|
+
end
|
167
|
+
|
168
|
+
def debug_format_result(dep, spec_groups)
|
169
|
+
a = [dep.to_s,
|
170
|
+
spec_groups.map {|sg| [sg.version, sg.dependencies_for_activated_platforms.map {|dp| [dp.name, dp.requirement.to_s] }] }]
|
171
|
+
last_map = a.last.map {|sg_data| [sg_data.first.version, sg_data.last.map {|aa| aa.join(" ") }] }
|
172
|
+
[a.first, last_map, level, strict ? :strict : :not_strict]
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
data/lib/bundler/graph.rb
CHANGED
@@ -17,7 +17,6 @@ module Bundler
|
|
17
17
|
@node_options = {}
|
18
18
|
@edge_options = {}
|
19
19
|
|
20
|
-
_patching_gem_dependency_class
|
21
20
|
_populate_relations
|
22
21
|
end
|
23
22
|
|
@@ -36,10 +35,7 @@ module Bundler
|
|
36
35
|
|
37
36
|
tmp = Set.new
|
38
37
|
parent_dependencies.each do |dependency|
|
39
|
-
|
40
|
-
dependency.prerelease = true
|
41
|
-
|
42
|
-
child_dependencies = dependency.to_spec.runtime_dependencies.to_set
|
38
|
+
child_dependencies = spec_for_dependency(dependency).runtime_dependencies.to_set
|
43
39
|
@relations[dependency.name] += child_dependencies.map(&:name).to_set
|
44
40
|
tmp += child_dependencies
|
45
41
|
|
@@ -74,7 +70,7 @@ module Bundler
|
|
74
70
|
when :node
|
75
71
|
if symbol_or_string_or_dependency.is_a?(Gem::Dependency)
|
76
72
|
label = symbol_or_string_or_dependency.name.dup
|
77
|
-
label << "\n#{symbol_or_string_or_dependency.
|
73
|
+
label << "\n#{spec_for_dependency(symbol_or_string_or_dependency).version}" if @show_version
|
78
74
|
else
|
79
75
|
label = symbol_or_string_or_dependency.to_s
|
80
76
|
end
|
@@ -90,25 +86,8 @@ module Bundler
|
|
90
86
|
label.nil? ? {} : { :label => label }
|
91
87
|
end
|
92
88
|
|
93
|
-
def
|
94
|
-
|
95
|
-
# redefinition of matching_specs will also redefine to_spec and to_specs
|
96
|
-
Gem::Dependency.class_eval do
|
97
|
-
def matching_specs(platform_only = false)
|
98
|
-
matches = Bundler.load.specs.select do |spec|
|
99
|
-
name == spec.name &&
|
100
|
-
requirement.satisfied_by?(spec.version)
|
101
|
-
end
|
102
|
-
|
103
|
-
if platform_only
|
104
|
-
matches.select! do |spec|
|
105
|
-
Gem::Platform.match spec.platform
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
matches = matches.sort_by(&:sort_obj) # HACK: shouldn't be needed
|
110
|
-
end
|
111
|
-
end
|
89
|
+
def spec_for_dependency(dependency)
|
90
|
+
@env.requested_specs.find {|s| s.name == dependency.name }
|
112
91
|
end
|
113
92
|
|
114
93
|
class GraphVizClient
|
data/lib/bundler/index.rb
CHANGED
@@ -67,12 +67,20 @@ module Bundler
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
-
results
|
70
|
+
sort_specs(results)
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.sort_specs(specs)
|
74
|
+
specs.sort_by do |s|
|
71
75
|
platform_string = s.platform.to_s
|
72
76
|
[s.version, platform_string == RUBY ? NULL : platform_string]
|
73
77
|
end
|
74
78
|
end
|
75
79
|
|
80
|
+
def sort_specs(specs)
|
81
|
+
self.class.sort_specs(specs)
|
82
|
+
end
|
83
|
+
|
76
84
|
def local_search(query, base = nil)
|
77
85
|
case query
|
78
86
|
when Gem::Specification, RemoteSpecification, LazySpecification, EndpointSpecification then search_by_spec(query)
|
data/lib/bundler/injector.rb
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module Bundler
|
3
3
|
class Injector
|
4
|
-
def self.inject(new_deps)
|
5
|
-
injector = new(new_deps)
|
4
|
+
def self.inject(new_deps, options = {})
|
5
|
+
injector = new(new_deps, options)
|
6
6
|
injector.inject(Bundler.default_gemfile, Bundler.default_lockfile)
|
7
7
|
end
|
8
8
|
|
9
|
-
def initialize(new_deps)
|
9
|
+
def initialize(new_deps, options = {})
|
10
10
|
@new_deps = new_deps
|
11
|
+
@options = options
|
11
12
|
end
|
12
13
|
|
13
14
|
def inject(gemfile_path, lockfile_path)
|
@@ -48,14 +49,20 @@ module Bundler
|
|
48
49
|
|
49
50
|
def new_gem_lines
|
50
51
|
@new_deps.map do |d|
|
51
|
-
|
52
|
+
name = "'#{d.name}'"
|
53
|
+
requirement = ", '#{d.requirement}'"
|
54
|
+
group = ", :group => #{d.groups.inspect}" if d.groups != Array(:default)
|
55
|
+
source = ", :source => '#{d.source}'" unless d.source.nil?
|
56
|
+
%(gem #{name}#{requirement}#{group}#{source})
|
52
57
|
end.join("\n")
|
53
58
|
end
|
54
59
|
|
55
60
|
def append_to(gemfile_path)
|
56
61
|
gemfile_path.open("a") do |f|
|
57
62
|
f.puts
|
58
|
-
|
63
|
+
if @options["timestamp"] || @options["timestamp"].nil?
|
64
|
+
f.puts "# Added at #{Time.now} by #{`whoami`.chomp}:"
|
65
|
+
end
|
59
66
|
f.puts new_gem_lines
|
60
67
|
end
|
61
68
|
end
|