Skip to content

Commit 731fd29

Browse files
committed
68 #40 Ruby Pattern like GitHub Codebase
1 parent 1342be7 commit 731fd29

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

script/.gitkeep

Whitespace-only changes.

script/bootstrap

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#!/usr/bin/env ruby
2+
#/ Usage: script/bootstrap [<options>]
3+
#/ Bootstraps the gem environment.
4+
#/
5+
#/ Options are passed through to the bundle-install command. In most cases you
6+
#/ won't need these. They're used primarily in production environments.
7+
#/ --local use gems in vendor/cache instead of rubygems.org
8+
#/ --without=<groups> do not install gems in the groups specified
9+
#
10+
# =============================================================================
11+
# Uses bundler to install all gems specified in the Gemfile under vendor/gems,
12+
# records the load path in config/loadpath, and generates bundler-free binstubs
13+
# under bin.
14+
#
15+
# The basic idea is to use bundler to install necessary gems but not
16+
# rely on it to manage the load path at runtime because it's slow. Requiring
17+
# 'bundler/setup' takes ~500ms user CPU time in production and ~1500ms in
18+
# development/test. This makes it unusable in scenarios that require a fast
19+
# boot (e.g., script/gerve, proxymachine daemons, ernie/smoke, etc.). It's also
20+
# a problem in development where it slows tools like rake command line
21+
# completion to a crawl and adds at least a second to single-file test runs.
22+
#
23+
# There's very little reason to use bundler at runtime since everything
24+
# is known at install time. We simply save off the result of the work done by
25+
# bundle/setup and use it until bundle-install is run again.
26+
27+
# show usage message with --help
28+
if ARGV.include?('--help')
29+
system "grep '^#/' <'#{__FILE__}' |cut -c4-"
30+
exit 2
31+
end
32+
33+
# go into the project root because it makes everything easier
34+
root = File.expand_path('../..', __FILE__)
35+
Dir.chdir(root)
36+
37+
# point bundler to the right stuff
38+
ENV['BUNDLE_GEMFILE'] = "#{root}/Gemfile"
39+
ENV['BUNDLE_PATH'] = "#{root}/vendor/gems"
40+
41+
# bring in rubygems and make sure bundler is installed.
42+
require 'rubygems'
43+
begin
44+
require 'bundler'
45+
rescue LoadError => boom
46+
warn "Bundler not found. Install it with `gem install bundler' and try again."
47+
exit 0
48+
end
49+
50+
# record the Gemfile checksum so we can tell if the Gemfile has changed
51+
# since our loadpath was last generated. this is used in config/basic.rb
52+
# to verify the environment is bootstrapped and up-to-date.
53+
checksum = `cksum Gemfile`.to_i
54+
installed = File.read('.bundle/checksum').to_i rescue nil
55+
56+
# run a quick check to see if everything's installed and up-to-date so we can
57+
# skip the install and loadpath generation step if possible.
58+
if checksum == installed && system('bundle check 1>/dev/null 2>&1')
59+
puts "Gem environment up-to-date."
60+
else
61+
# run bundle-install to install any missing gems
62+
argv = ['--no-color', 'install', '--path', 'vendor/gems'] + ARGV
63+
system("bundle", *argv) || begin
64+
warn "bundle executable not found. Ensure bundler is installed (`gem " +
65+
"install bundler`) and that the gem bin path is in your PATH"
66+
exit($?.exitstatus)
67+
end
68+
69+
# load the Gemfile
70+
bundle = Bundler.setup
71+
72+
# extract load paths for each gem and write to the config/loadpath file.
73+
load_paths = []
74+
bundle.gems.each do |gem|
75+
next if gem.name == 'bundler'
76+
gem.load_paths.each do |path|
77+
if path[0, root.size] == root
78+
path = path[(root.size + 1), path.size]
79+
load_paths << path
80+
else
81+
warn "external load path directory detected: #{path}"
82+
end
83+
end
84+
end
85+
86+
# move the loadpath and checksum files into place if everything was installed
87+
# okay and the load path file was written successfully.
88+
File.open('.bundle/loadpath+', 'wb') { |fd| fd.write(load_paths.join("\n")) }
89+
File.rename('.bundle/loadpath+', '.bundle/loadpath')
90+
File.open('.bundle/checksum', 'wb') { |fd| fd.puts(checksum) }
91+
92+
# write binstubs for all executables. we can't use bundler's --binstubs option
93+
# because the generated executables require 'bundler/setup'. the binstubs
94+
# generated here require only config/basic.rb, which sets up the loadpath
95+
# manually using the .bundle/loadpath file.
96+
Dir.mkdir "bin" unless File.directory?("bin")
97+
template = DATA.read
98+
lineno = File.read(__FILE__).count("\n") - template.count("\n")
99+
bundle.gems.each do |spec|
100+
spec.executables.each do |executable|
101+
script = eval('%Q{' + template + '}', binding, __FILE__, lineno)
102+
File.open("bin/#{executable}+", 'wb') { |fd| fd.write(script) }
103+
File.chmod 0755, "bin/#{executable}+"
104+
File.rename("bin/#{executable}+", "bin/#{executable}")
105+
end
106+
end
107+
end
108+
109+
__END__
110+
#!/usr/bin/env #{RbConfig::CONFIG['ruby_install_name']}
111+
#
112+
# This file was generated by script/bootstrap.
113+
root = File.expand_path('../..', __FILE__)
114+
require "#\{root\}/config/load"
115+
gem_path = "#{spec.full_gem_path.sub(root, "#\{root\}")}"
116+
load File.join(gem_path, '#{spec.bindir}', '#{executable}')
117+

0 commit comments

Comments
 (0)