prebundler 0.0.4 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/lib/prebundler/cli/install.rb +69 -11
- data/lib/prebundler/gem_ref.rb +25 -11
- data/lib/prebundler/gemfile.rb +14 -0
- data/lib/prebundler/gemfile_interpreter.rb +12 -9
- data/lib/prebundler/git_gem_ref.rb +18 -9
- data/lib/prebundler/path_gem_ref.rb +19 -1
- data/lib/prebundler/version.rb +1 -1
- data/prebundler.gemspec +1 -2
- metadata +2 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8f3573257ed6d3ae187bd8cc9b3e37ce6787373
|
4
|
+
data.tar.gz: 7780812efb908e7e533e1e7a3299b529f281bda5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 51e0f4e6e61305cd9535de52ca2bd3366694f63b99a0ea43d20ac084571815be95683a035698983ea0aa7eaeb4f14bf903f97aecb7b32988df1d4d296ba0834d
|
7
|
+
data.tar.gz: b1890c8532ddce82b3da898d5aae18d1c5da929b328fd460df090949310d5c70ec2d3cd3f7c98bdb1b2315fd44875e60b4594e2f91de7a87c115bb94683edbab
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'securerandom'
|
2
2
|
require 'tmpdir'
|
3
3
|
require 'parallel'
|
4
|
-
require '
|
4
|
+
require 'fileutils'
|
5
|
+
require 'yaml'
|
5
6
|
|
6
7
|
module Prebundler
|
7
8
|
module Cli
|
@@ -9,15 +10,34 @@ module Prebundler
|
|
9
10
|
def run
|
10
11
|
prepare
|
11
12
|
install
|
13
|
+
update_bundle_config
|
14
|
+
generate_binstubs
|
12
15
|
check
|
13
16
|
end
|
14
17
|
|
15
18
|
private
|
16
19
|
|
17
20
|
def prepare
|
18
|
-
|
21
|
+
FileUtils.mkdir_p(bundle_path)
|
22
|
+
|
23
|
+
gem_list.each do |name, gem_ref|
|
19
24
|
next if backend_file_list.include?(gem_ref.tar_file)
|
20
25
|
next unless member_of_installable_group?(gem_ref)
|
26
|
+
|
27
|
+
# Edge case: installation could fail if dependencies of this
|
28
|
+
# gem ref haven't been installed yet. They should have been
|
29
|
+
# prepared by this point because of the tsort logic in the
|
30
|
+
# gemfile class, but we need to actually install them in
|
31
|
+
# order to install this current gem. A good example is nokogiri,
|
32
|
+
# which can't build its native extension without mini-portile2.
|
33
|
+
gem_ref.dependencies.each do |dep|
|
34
|
+
if gem_list.gems[dep]
|
35
|
+
install_gem_ref(gem_list.gems[dep])
|
36
|
+
else
|
37
|
+
out.puts "Oops, couldn't find dependency #{dep}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
21
41
|
install_gem(gem_ref) if gem_ref.installable?
|
22
42
|
end
|
23
43
|
end
|
@@ -79,17 +99,51 @@ module Prebundler
|
|
79
99
|
config.storage_backend.store_file(dest_file, gem_ref.tar_file)
|
80
100
|
end
|
81
101
|
|
102
|
+
def update_bundle_config
|
103
|
+
file = Bundler.app_config_path.join('config').to_s
|
104
|
+
config = File.exist?(file) ? YAML.load_file(file) : {}
|
105
|
+
config['BUNDLE_WITH'] = with_groups.join(':') unless with_groups.empty?
|
106
|
+
config['BUNDLE_WITHOUT'] = without_groups.join(':') unless without_groups.empty?
|
107
|
+
File.write(file, YAML.dump(config))
|
108
|
+
end
|
109
|
+
|
110
|
+
def generate_binstubs
|
111
|
+
out.puts 'Generating binstubs...'
|
112
|
+
|
113
|
+
gems_with_executables = gem_list.gems.values.select do |gem_ref|
|
114
|
+
next false unless member_of_installable_group?(gem_ref)
|
115
|
+
!gem_ref.executables.empty?
|
116
|
+
end
|
117
|
+
|
118
|
+
return if gems_with_executables.empty?
|
119
|
+
|
120
|
+
system "bundle binstubs #{gems_with_executables.map(&:name).join(' ')}"
|
121
|
+
system "bundle binstubs --force bundler"
|
122
|
+
out.puts 'Done generating binstubs'
|
123
|
+
end
|
124
|
+
|
82
125
|
def check
|
83
|
-
system
|
126
|
+
system "bundle check --gemfile #{gemfile_path}"
|
84
127
|
|
85
128
|
if $?.exitstatus != 0
|
86
129
|
out.puts 'Bundle not satisfied, falling back to `bundle install`'
|
87
|
-
system
|
130
|
+
system "bundle install #{bundle_install_args}"
|
88
131
|
end
|
89
132
|
end
|
90
133
|
|
134
|
+
def bundle_install_args
|
135
|
+
[].tap do |args|
|
136
|
+
args << "--gemfile #{gemfile_path}"
|
137
|
+
args << "--with #{with_groups}" unless with_groups.empty?
|
138
|
+
args << "--without #{without_groups}" unless without_groups.empty?
|
139
|
+
args << "--jobs #{options[:jobs]}"
|
140
|
+
end.join(' ')
|
141
|
+
end
|
142
|
+
|
91
143
|
def gem_list
|
92
|
-
@gem_list ||= Prebundler::GemfileInterpreter.interpret(
|
144
|
+
@gem_list ||= Prebundler::GemfileInterpreter.interpret(
|
145
|
+
gemfile_path, bundle_path
|
146
|
+
)
|
93
147
|
end
|
94
148
|
|
95
149
|
def backend_file_list
|
@@ -115,14 +169,18 @@ module Prebundler
|
|
115
169
|
|
116
170
|
def groups
|
117
171
|
@groups ||= begin
|
118
|
-
all_groups = gem_list.flat_map { |_, gem_ref| gem_ref.groups }.uniq
|
119
|
-
|
120
|
-
without_groups = (options[:without] || '').split(',').map { |g| g.strip.to_sym }
|
121
|
-
|
122
|
-
groups = with_groups.empty? ? all_groups : with_groups
|
123
|
-
groups - without_groups
|
172
|
+
all_groups = gem_list.flat_map { |_, gem_ref| gem_ref.groups.to_a }.uniq
|
173
|
+
(all_groups + with_groups).uniq - without_groups
|
124
174
|
end
|
125
175
|
end
|
176
|
+
|
177
|
+
def with_groups
|
178
|
+
@with_groups ||= (options[:with] || '').split(/[:, ]/).map { |g| g.strip.to_sym }
|
179
|
+
end
|
180
|
+
|
181
|
+
def without_groups
|
182
|
+
@without_groups ||= (options[:without] || '').split(/[:, ]/).map { |g| g.strip.to_sym }
|
183
|
+
end
|
126
184
|
end
|
127
185
|
end
|
128
186
|
end
|
data/lib/prebundler/gem_ref.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'fileutils'
|
2
|
+
require 'set'
|
2
3
|
|
3
4
|
module Prebundler
|
4
5
|
class GemRef
|
@@ -12,13 +13,13 @@ module Prebundler
|
|
12
13
|
end
|
13
14
|
end
|
14
15
|
|
15
|
-
attr_reader :name, :bundle_path
|
16
|
+
attr_reader :name, :bundle_path, :groups
|
16
17
|
attr_accessor :spec, :dependencies
|
17
18
|
|
18
19
|
def initialize(name, bundle_path, options = {})
|
19
20
|
@name = name
|
20
21
|
@bundle_path = bundle_path
|
21
|
-
@groups = options[:groups]
|
22
|
+
@groups = Set.new(options[:groups])
|
22
23
|
@source = options[:source]
|
23
24
|
@dependencies = options[:dependencies]
|
24
25
|
end
|
@@ -27,10 +28,6 @@ module Prebundler
|
|
27
28
|
@dependencies ||= []
|
28
29
|
end
|
29
30
|
|
30
|
-
def groups
|
31
|
-
@groups ||= []
|
32
|
-
end
|
33
|
-
|
34
31
|
def source
|
35
32
|
@source ||= DEFAULT_SOURCE
|
36
33
|
end
|
@@ -44,8 +41,8 @@ module Prebundler
|
|
44
41
|
end
|
45
42
|
|
46
43
|
def install
|
47
|
-
system "gem install -N
|
48
|
-
$?.exitstatus
|
44
|
+
system({ "GEM_HOME" => bundle_path }, "gem install -N --ignore-dependencies --source #{source} #{name} -v #{version}")
|
45
|
+
$?.exitstatus
|
49
46
|
end
|
50
47
|
|
51
48
|
def install_from_tar(tar_file)
|
@@ -57,11 +54,28 @@ module Prebundler
|
|
57
54
|
tar_flags = File.exist?(tar_file) ? '-rf' : '-cf'
|
58
55
|
|
59
56
|
system "tar -C #{bundle_path} #{tar_flags} #{tar_file} #{relative_gem_dir}"
|
60
|
-
|
57
|
+
|
58
|
+
relative_gemspec_files.each do |relative_gemspec_file|
|
59
|
+
system "tar -C #{bundle_path} -rf #{tar_file} #{relative_gemspec_file}"
|
60
|
+
end
|
61
61
|
|
62
62
|
if File.directory?(extension_dir)
|
63
63
|
system "tar -C #{bundle_path} -rf #{tar_file} #{relative_extension_dir}"
|
64
64
|
end
|
65
|
+
|
66
|
+
executables.each do |executable|
|
67
|
+
system "tar -C #{bundle_path} -rf #{tar_file} #{File.join('bin', executable)}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def executables
|
72
|
+
gemspecs.flat_map(&:executables)
|
73
|
+
end
|
74
|
+
|
75
|
+
def gemspecs
|
76
|
+
@gemspecs ||= relative_gemspec_files.map do |relative_gemspec_file|
|
77
|
+
Bundler.load_gemspec(File.join(bundle_path, relative_gemspec_file))
|
78
|
+
end
|
65
79
|
end
|
66
80
|
|
67
81
|
def installable?
|
@@ -96,8 +110,8 @@ module Prebundler
|
|
96
110
|
File.join('gems', id)
|
97
111
|
end
|
98
112
|
|
99
|
-
def
|
100
|
-
File.join('specifications', gemspec_file)
|
113
|
+
def relative_gemspec_files
|
114
|
+
[File.join('specifications', gemspec_file)]
|
101
115
|
end
|
102
116
|
|
103
117
|
def tar_file
|
data/lib/prebundler/gemfile.rb
CHANGED
@@ -9,6 +9,10 @@ module Prebundler
|
|
9
9
|
|
10
10
|
def initialize(gems)
|
11
11
|
@gems = gems
|
12
|
+
|
13
|
+
gems.each do |_, gem_ref|
|
14
|
+
assign_groups(gem_ref, [])
|
15
|
+
end
|
12
16
|
end
|
13
17
|
|
14
18
|
def each
|
@@ -23,6 +27,16 @@ module Prebundler
|
|
23
27
|
|
24
28
|
private
|
25
29
|
|
30
|
+
# propagate groups to dependencies
|
31
|
+
def assign_groups(gem_ref, seen)
|
32
|
+
gem_ref.dependencies.each do |dep|
|
33
|
+
next if seen.include?(dep)
|
34
|
+
next unless gems[dep]
|
35
|
+
gem_ref.groups.each { |group| gems[dep].groups << group }
|
36
|
+
assign_groups(gems[dep], seen + [dep])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
26
40
|
def tsort_each_node(&block)
|
27
41
|
gems.keys.each(&block)
|
28
42
|
end
|
@@ -1,18 +1,21 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
1
3
|
module Prebundler
|
2
4
|
class GemfileInterpreter
|
3
|
-
def self.interpret(
|
4
|
-
Gemfile.new(new(
|
5
|
+
def self.interpret(gemfile_path, bundle_path)
|
6
|
+
Gemfile.new(new(gemfile_path, bundle_path).gems)
|
5
7
|
end
|
6
8
|
|
7
|
-
attr_reader :gems, :bundle_path
|
9
|
+
attr_reader :gems, :gemfile_path, :bundle_path
|
8
10
|
|
9
|
-
def initialize(
|
11
|
+
def initialize(gemfile_path, bundle_path)
|
10
12
|
@gems = {}
|
11
|
-
@current_groups = []
|
13
|
+
@current_groups = [:global]
|
14
|
+
@gemfile_path = gemfile_path
|
12
15
|
@bundle_path = bundle_path
|
13
|
-
instance_eval(File.read(
|
16
|
+
instance_eval(File.read(gemfile_path))
|
14
17
|
|
15
|
-
lockfile = Bundler::LockfileParser.new(File.read("#{
|
18
|
+
lockfile = Bundler::LockfileParser.new(File.read("#{gemfile_path}.lock"))
|
16
19
|
|
17
20
|
lockfile.specs.each do |spec|
|
18
21
|
gems[spec.name] ||= GemRef.create(spec.name, bundle_path)
|
@@ -35,7 +38,7 @@ module Prebundler
|
|
35
38
|
end
|
36
39
|
|
37
40
|
def path(dir)
|
38
|
-
@current_path = dir
|
41
|
+
@current_path = File.join(File.dirname(gemfile_path), dir)
|
39
42
|
yield if block_given?
|
40
43
|
@current_path = nil
|
41
44
|
end
|
@@ -49,7 +52,7 @@ module Prebundler
|
|
49
52
|
def group(*groups)
|
50
53
|
@current_groups = groups
|
51
54
|
yield if block_given?
|
52
|
-
@current_groups = []
|
55
|
+
@current_groups = [:global]
|
53
56
|
end
|
54
57
|
|
55
58
|
def gemspec
|
@@ -15,10 +15,13 @@ module Prebundler
|
|
15
15
|
def initialize(name, bundle_path, options = {})
|
16
16
|
super
|
17
17
|
@strategy = options.include?(:git) ? :git : :github
|
18
|
-
@uri = options[@strategy]
|
19
18
|
end
|
20
19
|
|
21
20
|
def install
|
21
|
+
FileUtils.mkdir_p(spec_path)
|
22
|
+
FileUtils.mkdir_p(install_path)
|
23
|
+
FileUtils.mkdir_p(cache_path)
|
24
|
+
|
22
25
|
return if File.exist?(cache_dir) || File.exist?(install_dir)
|
23
26
|
system "git clone #{uri} \"#{cache_dir}\" --bare --no-hardlinks --quiet"
|
24
27
|
return $? if $?.exitstatus != 0
|
@@ -55,11 +58,7 @@ module Prebundler
|
|
55
58
|
end
|
56
59
|
|
57
60
|
def uri
|
58
|
-
|
59
|
-
"git://github.com/#{@uri}.git"
|
60
|
-
else
|
61
|
-
@uri
|
62
|
-
end
|
61
|
+
spec.source.uri
|
63
62
|
end
|
64
63
|
|
65
64
|
alias_method :source, :uri
|
@@ -68,16 +67,26 @@ module Prebundler
|
|
68
67
|
spec.source.revision
|
69
68
|
end
|
70
69
|
|
70
|
+
def gemspecs
|
71
|
+
@gemspecs ||= gemspec_files.map do |gemspec_file|
|
72
|
+
Bundler.load_gemspec(gemspec_file)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
71
76
|
private
|
72
77
|
|
78
|
+
def gemspec_files
|
79
|
+
@gemspec_files ||= Dir[File.join(install_dir, '*.gemspec')]
|
80
|
+
end
|
81
|
+
|
73
82
|
def copy_gemspecs
|
74
|
-
FileUtils.cp(
|
83
|
+
FileUtils.cp(gemspec_files, spec_path)
|
75
84
|
end
|
76
85
|
|
77
86
|
# adapted from
|
78
87
|
# https://github.com/bundler/bundler/blob/fea23637886c1b1bde471c98344b8844f82e60ce/lib/bundler/source/git.rb#L237
|
79
88
|
def serialize_gemspecs
|
80
|
-
|
89
|
+
gemspec_files.each do |path|
|
81
90
|
# Evaluate gemspecs and cache the result. Gemspecs
|
82
91
|
# in git might require git or other dependencies.
|
83
92
|
# The gemspecs we cache should already be evaluated.
|
@@ -100,7 +109,7 @@ module Prebundler
|
|
100
109
|
# If there is no URI scheme, assume it is an ssh/git URI
|
101
110
|
input = uri
|
102
111
|
end
|
103
|
-
|
112
|
+
Bundler::SharedHelpers.digest(:SHA1).hexdigest(input)
|
104
113
|
end
|
105
114
|
end
|
106
115
|
end
|
@@ -10,7 +10,11 @@ module Prebundler
|
|
10
10
|
|
11
11
|
def initialize(name, bundle_path, options = {})
|
12
12
|
super
|
13
|
-
|
13
|
+
|
14
|
+
# @TODO: Individual gem calls can also specify a path, which
|
15
|
+
# we don't currently handle. For now just use the gem's name
|
16
|
+
# to complete the path.
|
17
|
+
@path = File.join(options[:path], name)
|
14
18
|
end
|
15
19
|
|
16
20
|
def installable?
|
@@ -21,6 +25,20 @@ module Prebundler
|
|
21
25
|
false
|
22
26
|
end
|
23
27
|
|
28
|
+
def gemspecs
|
29
|
+
@gemspecs ||= gemspec_files.map do |gemspec_file|
|
30
|
+
Dir.chdir(File.dirname(gemspec_file)) do
|
31
|
+
Bundler.load_gemspec(File.basename(gemspec_file))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
24
36
|
alias_method :source, :path
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def gemspec_files
|
41
|
+
@gemspec_files ||= Dir[File.join(path, '*.gemspec')]
|
42
|
+
end
|
25
43
|
end
|
26
44
|
end
|
data/lib/prebundler/version.rb
CHANGED
data/prebundler.gemspec
CHANGED
@@ -17,9 +17,8 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.add_dependency 'parallel', '~> 1.0'
|
18
18
|
s.add_dependency 'gli', '~> 2.0'
|
19
19
|
|
20
|
-
# @TODO:
|
20
|
+
# @TODO: move s3 support into separate gem
|
21
21
|
s.add_dependency 'aws-sdk', '~> 2.0'
|
22
|
-
s.add_dependency 'pry-byebug'
|
23
22
|
|
24
23
|
s.executables << 'prebundle'
|
25
24
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prebundler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cameron Dutro
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-12-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -66,20 +66,6 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '2.0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: pry-byebug
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
76
|
-
type: :runtime
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
69
|
description: Gem dependency prebuilder
|
84
70
|
email:
|
85
71
|
- camertron@gmail.com
|