1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
#!/usr/bin/env ruby
require "rubygems"
require "bundler"
Bundler.with_clean_env do
require_relative "../gemfile_util"
options = {}
opts = OptionParser.new do |opts|
opts.banner = "Usage: create-override-gemfile [OPTIONS]"
opts.on("--gemfile GEMFILE", "The Gemfile to read (default: Gemfile).") { |path| options[:gemfile_path] = path }
opts.on("--lockfile GEMFILE", "The lockfile to read (default: <gemfile>.lock).") { |path| options[:lockfile_path] = path }
opts.on("--group GROUP", "Groups to include (whitelist).") do |group|
options[:groups] ||= []
options[:groups] << group.to_sym
end
opts.on("--without GROUP", "Groups to exclude.") do |group|
options[:without_groups] ||= []
options[:without_groups] << group.to_sym
end
opts.on("--gem GEM", "Gems to include regardless of groups.") do |name|
options[:gems] ||= []
options[:gems] << name
end
opts.on("--relative-to PATH", "A path to prepend to any relative paths in the Gemfile.") do |path|
unless Pathname.new(path).absolute?
puts opts
raise "--relative-to #{path} was not an absolute path!"
end
options[:relative_to] = path
end
opts.on("--[no-]copy-groups", "Whether to copy groups over from the original Gemfile or not (default: false).") { |val| options[:copy_groups] = val }
opts.on("--[no-]override", "Whether to emit override: true on each gem line (default: false).") { |val| options[:override] = val }
opts.on("-h", "--help", "Print this message.") do
puts opts
exit(0)
end
end
args = opts.parse(ARGV)
if args.size > 0
puts opts
raise "Invalid arguments #{args}"
end
def create_override_gemfile(gemfile_path: "Gemfile", lockfile_path: "#{gemfile_path}.lock", groups: nil, without_groups: nil, gems: [], copy_groups: false, relative_to: ".", override: false)
relative_to = Pathname.new(relative_to).realpath
# Select the gems we want
bundle = GemfileUtil::Bundle.parse(gemfile_path, lockfile_path)
gems_to_include = bundle.select_gems(groups: groups, without_groups: without_groups)
gems.each do |name|
raise "Requested gem #{name} is not in #{gemfile_path}.lock!" if !bundle.gems[name]
gems_to_include[name] ||= bundle.gems[name]
gems_to_include[name][:dependencies].each do |dep|
gems_to_include[name] ||= bundle.gems[dep]
end
end
# Add the gems to the Gemfile
gem_root = Pathname.new(gemfile_path).dirname.realpath
gems_to_include.sort_by { |name, options| options[:declared_groups].empty? ? 1 : 0 }.each do |name, options|
comment = nil
options = options.dup
version = options.delete(:version)
if copy_groups
# Some dependencies have no groups (are not in the Gemfile--just runtime
# dependencies). If we actually record that they have no groups, they
# will *always* be installed (or perhaps never). We only want them to
# install if their other deps do, so we mark them with the groups of the
# things that brought them in (the gems that depended on them). To do
# this, we just leave :groups intact.
if options[:declared_groups].empty?
options.delete(:declared_groups)
comment = " # Transitive dependency, not actually in original Gemfile"
else
# For other things, we want to copy the actual declared_groups--the
# ones that were in the Gemfile. We want the same --with and --without
# options to include and exclude them as worked with the original
# Gemfile.
options[:groups] = options.delete(:declared_groups)
end
else
options.delete(:groups)
options.delete(:declared_groups)
end
options.delete(:dependencies)
options.delete(:development_dependencies)
options[:override] = true if override
options[:path] = Pathname.new(options[:path]).expand_path(gem_root).relative_path_from(relative_to).to_s if options[:path]
line = "gem #{name.inspect}, #{version.inspect}"
options.each do |name, value|
line << ", #{name}: #{value.inspect}"
end
line << comment if comment
puts line
end
end
create_override_gemfile(options)
end
|