rubygems-precompiled 0.0.1
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
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +42 -0
- data/Rakefile +1 -0
- data/features/installing_with_cache.feature +47 -0
- data/features/precompiling_gems.feature +46 -0
- data/features/steps/command_steps.rb +64 -0
- data/features/steps/file_steps.rb +37 -0
- data/features/steps/rubygem_steps.rb +0 -0
- data/lib/rubygems/commands/precompile_command.rb +45 -0
- data/lib/rubygems/precompiled.rb +118 -0
- data/lib/rubygems/precompiled/version.rb +5 -0
- data/lib/rubygems/precompiler.rb +108 -0
- data/lib/rubygems_plugin.rb +4 -0
- data/rubygems-precompiled.gemspec +25 -0
- data/spec/fixtures/gem-sources.tar.gz +0 -0
- metadata +124 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 437a696f3109133c285f30281afb05a3a774ab5c
|
4
|
+
data.tar.gz: 1068539b91ba04f83dbd865c24aacbb048a0af00
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 72e124fac7166f9528fd155452d89d8aa263db8dd8a859113af2e4c874124b0758afd1ec15a1be0f06c2c675481f5e23d0baf478e5b4960863f7c5807aa70537
|
7
|
+
data.tar.gz: 40ff597a7dbd0190c05aac335ad6cda38c6bf2b01a69d44568a69a1737a70913e88fbeb2123584a92a6e6ed338be3a6fc2188c7c233c7fb1fcbdd505a5357157
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Thomas Haggett
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# Rubygems::Precompiled
|
2
|
+
|
3
|
+
This gem allows you to build the c-extensions of a ruby-gem on a host with build-tools installed, make the result available over HTTP, then use this on end machines that may not have build-tools installed.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
$ gem install rubygems-precompiled
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
There are two halves to this, the pre-compile on a build machine and the install
|
12
|
+
on machines that don't have the build-tools available.
|
13
|
+
|
14
|
+
### Build host
|
15
|
+
|
16
|
+
Fetch a gem you're interested in:
|
17
|
+
|
18
|
+
gem fetch foobar -v '0.1.0'
|
19
|
+
|
20
|
+
Pre-compile the gem into the correct folder structure:
|
21
|
+
|
22
|
+
gem precompile -a -o /output foobar-0.1.0.gem
|
23
|
+
|
24
|
+
Which will write the file:
|
25
|
+
|
26
|
+
/output/ruby-1.9.3p448/x86_64-linux/foobar-0.1.0.tar.gz
|
27
|
+
|
28
|
+
You need to make this directory structure available over HTTP, and available to the installation machines.
|
29
|
+
|
30
|
+
### Installation host
|
31
|
+
|
32
|
+
Configure the cache path (file:/// and http:// urls are supported at the moment) in `/etc/gemrc`:
|
33
|
+
|
34
|
+
precompiled_cache:
|
35
|
+
- http://some.server/ruby-gem-extensions/
|
36
|
+
|
37
|
+
Install a gem using the cache:
|
38
|
+
|
39
|
+
gem install foobar -v '0.1.0'
|
40
|
+
|
41
|
+
|
42
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,47 @@
|
|
1
|
+
Feature: Installing using a compiled-cache
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given I have wiped the folder "/tmp/precompiled-workroot"
|
5
|
+
|
6
|
+
# Scenario: Installing a compiled gem without the cache
|
7
|
+
|
8
|
+
Scenario: Installing a compiled gem with a cache miss
|
9
|
+
Given I use the gem configuration option
|
10
|
+
"""
|
11
|
+
precompiled_cache:
|
12
|
+
- file:///tmp/precompiled-workroot/cache
|
13
|
+
"""
|
14
|
+
|
15
|
+
When I execute "gem install --install-dir /tmp/precompiled-workroot/installroot spec/fixtures/compiled-gem.gem"
|
16
|
+
Then I should see "Building native extensions"
|
17
|
+
Then I should not see "Loading native extension from cache"
|
18
|
+
|
19
|
+
When I execute
|
20
|
+
"""
|
21
|
+
echo "puts CompiledClass.new.test_method" | ruby -I/tmp/precompiled-workroot/installroot/gems/compiled-gem-0.0.1/lib -rtest_ext/test_ext
|
22
|
+
"""
|
23
|
+
|
24
|
+
Then I should see "Hello, world!"
|
25
|
+
|
26
|
+
Scenario: Installing a compiled gem with a cache hit
|
27
|
+
Given I use the gem configuration option
|
28
|
+
"""
|
29
|
+
precompiled_cache:
|
30
|
+
- file:///tmp/precompiled-workroot/cache
|
31
|
+
"""
|
32
|
+
|
33
|
+
When I execute "gem precompile -o /tmp/precompiled-workroot/cache -a spec/fixtures/compiled-gem.gem"
|
34
|
+
|
35
|
+
And I execute "gem install --install-dir /tmp/precompiled-workroot/installroot spec/fixtures/compiled-gem.gem"
|
36
|
+
|
37
|
+
Then I should not see "Building native extensions"
|
38
|
+
Then I should see "Loading native extension from cache"
|
39
|
+
|
40
|
+
When I execute
|
41
|
+
"""
|
42
|
+
echo "puts CompiledClass.new.test_method" | ruby -I/tmp/precompiled-workroot/installroot/gems/compiled-gem-0.0.1/lib -rtest_ext/test_ext
|
43
|
+
"""
|
44
|
+
|
45
|
+
Then I should see "Hello, world!"
|
46
|
+
|
47
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
Feature: Pre-compiling gems
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given I have changed to a temporary directory containing "spec/fixtures/*.gem"
|
5
|
+
|
6
|
+
Scenario: Input validation
|
7
|
+
When I run the command "gem precompile"
|
8
|
+
Then I should see "Please specify a gem file on the command line, e.g. gem precompile foo-0.1.0.gem"
|
9
|
+
And the command should not return a success status code
|
10
|
+
|
11
|
+
Scenario: Pre-compiling a single gem
|
12
|
+
When I run the command "gem precompile simple-gem.gem"
|
13
|
+
|
14
|
+
Then I should see "The gem 'simple-gem' doesn't contain a compiled extension"
|
15
|
+
And the command should return a success status code
|
16
|
+
|
17
|
+
Scenario: Pre-compiling a single compiled gem
|
18
|
+
When I run the command "gem precompile compiled-gem.gem"
|
19
|
+
|
20
|
+
Then I should see "Compiling 'compiled-gem'..."
|
21
|
+
And the command should return a success status code
|
22
|
+
|
23
|
+
Scenario: Pre-compiling multiple gems
|
24
|
+
When I run the command "gem precompile *.gem"
|
25
|
+
|
26
|
+
Then I should see "The gem 'simple-gem' doesn't contain a compiled extension"
|
27
|
+
And I should see "Compiling 'compiled-gem'... done."
|
28
|
+
And the command should return a success status code
|
29
|
+
|
30
|
+
Scenario: Creating the flat output files
|
31
|
+
When I run the command "gem precompile *.gem"
|
32
|
+
|
33
|
+
Then the file "compiled-gem-0.0.1.tar.gz" should exist
|
34
|
+
And the file "simple-gem*.tar.gz" should not exist
|
35
|
+
|
36
|
+
Scenario: Writing to specific folder
|
37
|
+
When I run the command "gem precompile -o foo *.gem"
|
38
|
+
|
39
|
+
Then the folder "foo" should exist
|
40
|
+
And the file "foo/compiled-gem-0.0.1.tar.gz" should exist
|
41
|
+
|
42
|
+
Scenario: Creating architecture files
|
43
|
+
When I run the command "gem precompile -o foo -a *.gem"
|
44
|
+
|
45
|
+
Then the file "foo/ruby-*/x86_64-*/compiled-gem-0.0.1.tar.gz" should exist
|
46
|
+
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "tmpdir"
|
2
|
+
require 'fileutils'
|
3
|
+
require 'tempfile'
|
4
|
+
|
5
|
+
Given /^I use the gem configuration option$/ do |string|
|
6
|
+
File.open(File.expand_path("~/.gemrc"), "a") do |gemconfig|
|
7
|
+
gemconfig.puts("# --PURGE FROM HERE ---")
|
8
|
+
gemconfig.write string
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
After do
|
13
|
+
original, _ = File.read(File.expand_path("~/.gemrc")).split("# --PURGE FROM HERE ---")
|
14
|
+
File.open(File.expand_path("~/.gemrc"), "w") do |gemconfig|
|
15
|
+
gemconfig.write original
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def execute(command)
|
20
|
+
@last_stderr, @last_stdout = "", ""
|
21
|
+
|
22
|
+
stderr_r, stderr_w, stdout_r, stdout_w = [IO.pipe, IO.pipe].flatten
|
23
|
+
@command_env ||= {}
|
24
|
+
|
25
|
+
pid = spawn( @command_env, command, :out => stdout_w, :err => stderr_w)
|
26
|
+
_, status = Process.waitpid2(pid)
|
27
|
+
|
28
|
+
[stderr_w,stdout_w].each { |p| p.close }
|
29
|
+
|
30
|
+
@last_status = status.exitstatus
|
31
|
+
@last_stderr += stderr_r.read until stderr_r.eof?
|
32
|
+
@last_stdout += stdout_r.read until stdout_r.eof?
|
33
|
+
end
|
34
|
+
|
35
|
+
When /^I (?:run the command|execute) "(.*?)"$/ do |command|
|
36
|
+
execute(command)
|
37
|
+
end
|
38
|
+
When /^I (?:run the command|execute)$/ do |command|
|
39
|
+
execute(command)
|
40
|
+
end
|
41
|
+
|
42
|
+
Then /^I should( not)? see "(.*?)"( on (stdout|stderr))?$/ do |invert, expect, any, channel|
|
43
|
+
data = if channel.nil?
|
44
|
+
@last_stdout + @last_stderr
|
45
|
+
elsif channel == 'stdout'
|
46
|
+
@last_stdout
|
47
|
+
elsif channel == 'stderr'
|
48
|
+
@last_stderr
|
49
|
+
end
|
50
|
+
|
51
|
+
if invert
|
52
|
+
data.should_not include(expect)
|
53
|
+
else
|
54
|
+
data.should include(expect)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
Then /^the command should( not)? return a success status code$/ do |invert|
|
59
|
+
if invert
|
60
|
+
@last_status.should_not == 0
|
61
|
+
else
|
62
|
+
@last_status.should == 0
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
Given /^I have wiped the folder "(.*?)"$/ do |path|
|
3
|
+
FileUtils.rm_rf(path)
|
4
|
+
end
|
5
|
+
|
6
|
+
|
7
|
+
OriginalWorkingDirectory = Dir.pwd
|
8
|
+
Before do
|
9
|
+
FileUtils.chdir(OriginalWorkingDirectory)
|
10
|
+
end
|
11
|
+
cleanup = []
|
12
|
+
Given /^I have changed to a temporary directory(?: containing "(.*?)")?$/ do |glob|
|
13
|
+
directory = Dir.mktmpdir
|
14
|
+
cleanup << directory
|
15
|
+
if glob
|
16
|
+
files = Dir.glob(glob)
|
17
|
+
files.each do |file|
|
18
|
+
FileUtils.cp(file, File.join(directory, File.basename(file)))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
FileUtils.chdir(directory)
|
22
|
+
end
|
23
|
+
After do
|
24
|
+
cleanup.each { |dir| FileUtils.rm_rf(dir) }
|
25
|
+
end
|
26
|
+
|
27
|
+
Then /^the folder "(.*?)" should exist$/ do |folder|
|
28
|
+
File.directory?(folder).should be_true
|
29
|
+
end
|
30
|
+
|
31
|
+
Then /^the file "(.*?)" should (not )?exist$/ do |file, invert|
|
32
|
+
if invert
|
33
|
+
Dir.glob(file).should be_empty
|
34
|
+
else
|
35
|
+
Dir.glob(file).should_not be_empty
|
36
|
+
end
|
37
|
+
end
|
File without changes
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "rubygems/command"
|
2
|
+
|
3
|
+
class Gem::Commands::PrecompileCommand < Gem::Command
|
4
|
+
def initialize
|
5
|
+
super "precompile", "Create a bundle containing the compiled artifacts for this platform", :output => Dir.pwd, :arch => false
|
6
|
+
|
7
|
+
add_option('-o PATH', '--output=PATH', 'The output directory for the generated bundle. Defaults to the current directory') do |path,options|
|
8
|
+
options[:output] = path
|
9
|
+
end
|
10
|
+
|
11
|
+
add_option('-a','--arch-dirs','Adds the architecture sub-folders to the output directory before writing') do |arch, options|
|
12
|
+
options[:arch] = true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def arguments
|
17
|
+
"GEMFILE path to the gem file to compile"
|
18
|
+
end
|
19
|
+
|
20
|
+
def usage
|
21
|
+
"#{program_name} GEMFILE"
|
22
|
+
end
|
23
|
+
|
24
|
+
def execute
|
25
|
+
gemfiles = options[:args]
|
26
|
+
|
27
|
+
# no gem, no binary
|
28
|
+
if gemfiles.empty?
|
29
|
+
raise Gem::CommandLineError, "Please specify a gem file on the command line, e.g. #{program_name} foo-0.1.0.gem"
|
30
|
+
end
|
31
|
+
|
32
|
+
require "rubygems/precompiler"
|
33
|
+
|
34
|
+
gemfiles.each do |gemfile|
|
35
|
+
compiler = Gem::Precompiler.new(gemfile, options)
|
36
|
+
if compiler.has_extension?
|
37
|
+
$stderr.puts "Compiling '#{compiler.gem_name}'... "
|
38
|
+
compiler.compile
|
39
|
+
$stderr.puts "done."
|
40
|
+
else
|
41
|
+
$stderr.puts "The gem '#{compiler.gem_name}' doesn't contain a compiled extension"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'rubygems/precompiled/version'
|
2
|
+
require 'rubygems/installer'
|
3
|
+
require 'rubygems/ext/builder'
|
4
|
+
require 'rubygems/package/tar_reader'
|
5
|
+
require 'zlib'
|
6
|
+
require 'fileutils'
|
7
|
+
require 'net/http'
|
8
|
+
require 'uri'
|
9
|
+
require 'tempfile'
|
10
|
+
|
11
|
+
class Gem::Installer
|
12
|
+
|
13
|
+
class BaseCache
|
14
|
+
def initialize(root_uri)
|
15
|
+
@root_uri = root_uri
|
16
|
+
end
|
17
|
+
|
18
|
+
def retrieve(spec)
|
19
|
+
raise "Must be overriden!"
|
20
|
+
end
|
21
|
+
def contains?(spec)
|
22
|
+
false
|
23
|
+
end
|
24
|
+
def cache_key(spec)
|
25
|
+
"/ruby-#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}/#{Gem::Platform.local.to_s}/#{spec.name}-#{spec.version}.tar.gz"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class FileCache < BaseCache
|
30
|
+
def path_for(spec)
|
31
|
+
File.join(@root_uri.path, cache_key(spec))
|
32
|
+
end
|
33
|
+
def contains?(spec)
|
34
|
+
File.exists?(path_for(spec))
|
35
|
+
end
|
36
|
+
|
37
|
+
def retrieve(spec)
|
38
|
+
yield path_for(spec)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class HttpCache < BaseCache
|
43
|
+
def uri_to_spec(spec)
|
44
|
+
URI.join(@root_uri, File.join(@root_uri.path, cache_key(spec)))
|
45
|
+
end
|
46
|
+
def contains?(spec)
|
47
|
+
uri = uri_to_spec(spec)
|
48
|
+
http = Net::HTTP.start(uri.host, uri.port)
|
49
|
+
http.head(uri.path).code == "200"
|
50
|
+
end
|
51
|
+
def retrieve(spec)
|
52
|
+
tempfile = Tempfile.new('cache-hit')
|
53
|
+
uri = uri_to_spec(spec)
|
54
|
+
http = Net::HTTP.start(uri.host, uri.port)
|
55
|
+
http.request_get(uri.path) do |resp|
|
56
|
+
resp.read_body do |segment|
|
57
|
+
tempfile.write(segment)
|
58
|
+
end
|
59
|
+
tempfile.close
|
60
|
+
end
|
61
|
+
|
62
|
+
yield tempfile
|
63
|
+
tempfile.delete
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
GemCache = {
|
68
|
+
'file' => FileCache,
|
69
|
+
'http' => HttpCache
|
70
|
+
}.freeze
|
71
|
+
|
72
|
+
# Private: A list of precompiled cache root URLs loaded from the rubyges configuration file
|
73
|
+
#
|
74
|
+
# Returns Array of BaseCache subclasses
|
75
|
+
def self.precompiled_caches
|
76
|
+
@@caches ||= [Gem.configuration['precompiled_cache']].flatten.compact.map do |cache_root|
|
77
|
+
cache_root = URI.parse(cache_root)
|
78
|
+
GemCache[cache_root.scheme].new(cache_root)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def build_extensions_with_cache
|
83
|
+
cache = Gem::Installer.precompiled_caches.find { |cache| cache.contains?(@spec) }
|
84
|
+
|
85
|
+
if cache
|
86
|
+
puts "Loading native extension from cache"
|
87
|
+
cache.retrieve(@spec) do |path|
|
88
|
+
overlay_tarball(path)
|
89
|
+
end
|
90
|
+
else
|
91
|
+
build_extensions_without_cache
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
alias_method :build_extensions_without_cache, :build_extensions
|
96
|
+
alias_method :build_extensions, :build_extensions_with_cache
|
97
|
+
|
98
|
+
# Private: Extracts a .tar.gz file on-top of the gem's installation directory
|
99
|
+
def overlay_tarball(tarball)
|
100
|
+
Zlib::GzipReader.open(tarball) do |gzip_io|
|
101
|
+
Gem::Package::TarReader.new(gzip_io) do |tar|
|
102
|
+
tar.each do |entry|
|
103
|
+
target_path = File.join(gem_dir, entry.full_name)
|
104
|
+
if entry.directory?
|
105
|
+
FileUtils.mkdir_p(target_path)
|
106
|
+
elsif entry.file?
|
107
|
+
FileUtils.mkdir_p(File.dirname(target_path))
|
108
|
+
File.open(target_path, "w") do |f|
|
109
|
+
f.write entry.read(1024*1024) until entry.eof?
|
110
|
+
end
|
111
|
+
end
|
112
|
+
entry.close
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require "rbconfig"
|
2
|
+
require "tmpdir"
|
3
|
+
require "rubygems/installer"
|
4
|
+
require "fileutils"
|
5
|
+
require 'rubygems/package/tar_writer'
|
6
|
+
require 'zlib'
|
7
|
+
require 'pathname'
|
8
|
+
|
9
|
+
class Gem::Precompiler
|
10
|
+
include FileUtils
|
11
|
+
|
12
|
+
def initialize(gemfile, opts = {})
|
13
|
+
@installer = Gem::Installer.new(gemfile, opts.dup.merge(:unpack => true))
|
14
|
+
@target_dir = opts.fetch(:output, Dir.pwd)
|
15
|
+
@target_dir = File.join(@target_dir, arch_string) if opts.fetch(:arch, false)
|
16
|
+
@options = opts
|
17
|
+
end
|
18
|
+
|
19
|
+
# Public: Returns the name of hte gem
|
20
|
+
#
|
21
|
+
# Returns a string
|
22
|
+
def gem_name
|
23
|
+
@installer.spec.name
|
24
|
+
end
|
25
|
+
|
26
|
+
# Public: Does the gem actually have any compiled extensions?
|
27
|
+
#
|
28
|
+
# Returns boolean - true if the gem has a c-extension that needs building
|
29
|
+
def has_extension?
|
30
|
+
!@installer.spec.extensions.empty?
|
31
|
+
end
|
32
|
+
|
33
|
+
# Private: Yield the path to a temporary directory that will get deleted when
|
34
|
+
# the block returns
|
35
|
+
#
|
36
|
+
def tempdir
|
37
|
+
temp_dir = Dir.mktmpdir
|
38
|
+
yield temp_dir
|
39
|
+
ensure
|
40
|
+
rm_rf temp_dir
|
41
|
+
end
|
42
|
+
|
43
|
+
# Private: Return a string that uniquely keys this machines ruby version and architecture
|
44
|
+
#
|
45
|
+
# Returns string
|
46
|
+
def arch_string
|
47
|
+
"ruby-#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}/#{Gem::Platform.local.to_s}"
|
48
|
+
end
|
49
|
+
|
50
|
+
# Public: The filename of the compiled bundle for this gem
|
51
|
+
#
|
52
|
+
# Returns a string
|
53
|
+
def output_path
|
54
|
+
File.join(*[@target_dir, "#{@installer.spec.name}-#{@installer.spec.version}.tar.gz"].compact)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Private: Return a list fo build-products in a given directory
|
58
|
+
#
|
59
|
+
# Returns an array of paths
|
60
|
+
def build_products(installer, path)
|
61
|
+
dlext = RbConfig::CONFIG["DLEXT"]
|
62
|
+
lib_dirs = installer.spec.require_paths.join(',')
|
63
|
+
Dir.glob("#{path}/{#{lib_dirs}}/**/*.#{dlext}")
|
64
|
+
end
|
65
|
+
|
66
|
+
# Public: Compile
|
67
|
+
#
|
68
|
+
#
|
69
|
+
def compile
|
70
|
+
FileUtils.mkdir_p(@target_dir)
|
71
|
+
|
72
|
+
tempdir do |path|
|
73
|
+
@installer.unpack(path)
|
74
|
+
@installer.build_extensions
|
75
|
+
|
76
|
+
targz_file(output_path) do |tar_writer|
|
77
|
+
|
78
|
+
build_products(@installer, path).each do |product_path|
|
79
|
+
product_path = Pathname.new(product_path)
|
80
|
+
relative_path = product_path.relative_path_from(Pathname.new(path))
|
81
|
+
|
82
|
+
stat = File.stat(product_path)
|
83
|
+
mode = stat.mode
|
84
|
+
size = stat.size
|
85
|
+
|
86
|
+
File.open(product_path, "r") do |source|
|
87
|
+
|
88
|
+
tar_writer.add_file_simple(relative_path.to_s, mode, size) do |dest|
|
89
|
+
dest.write source.read(1024*1024) until source.eof?
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Private: Yield a reference to a TarWriter that writes to
|
100
|
+
# the specified .tar.gz file
|
101
|
+
#
|
102
|
+
def targz_file(path, &block)
|
103
|
+
Zlib::GzipWriter.open(path) do |tar_file_io|
|
104
|
+
Gem::Package::TarWriter.new(tar_file_io, &block)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rubygems/precompiled/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "rubygems-precompiled"
|
8
|
+
spec.version = Rubygems::Precompiled::VERSION
|
9
|
+
spec.authors = ["Thomas Haggett"]
|
10
|
+
spec.email = ["thomas-rubygemplugin@haggett.org"]
|
11
|
+
spec.description = %q{RubyGems plugin to allow a gem's compiled extension to be pre-built and cached}
|
12
|
+
spec.summary = spec.description
|
13
|
+
spec.homepage = "https://github.com/joshado/rubygems-precompiled"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "cucumber"
|
25
|
+
end
|
Binary file
|
metadata
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rubygems-precompiled
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Thomas Haggett
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-01-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: cucumber
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: RubyGems plugin to allow a gem's compiled extension to be pre-built and
|
70
|
+
cached
|
71
|
+
email:
|
72
|
+
- thomas-rubygemplugin@haggett.org
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- .gitignore
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE.txt
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- features/installing_with_cache.feature
|
83
|
+
- features/precompiling_gems.feature
|
84
|
+
- features/steps/command_steps.rb
|
85
|
+
- features/steps/file_steps.rb
|
86
|
+
- features/steps/rubygem_steps.rb
|
87
|
+
- lib/rubygems/commands/precompile_command.rb
|
88
|
+
- lib/rubygems/precompiled.rb
|
89
|
+
- lib/rubygems/precompiled/version.rb
|
90
|
+
- lib/rubygems/precompiler.rb
|
91
|
+
- lib/rubygems_plugin.rb
|
92
|
+
- rubygems-precompiled.gemspec
|
93
|
+
- spec/fixtures/gem-sources.tar.gz
|
94
|
+
homepage: https://github.com/joshado/rubygems-precompiled
|
95
|
+
licenses:
|
96
|
+
- MIT
|
97
|
+
metadata: {}
|
98
|
+
post_install_message:
|
99
|
+
rdoc_options: []
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - '>='
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - '>='
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
requirements: []
|
113
|
+
rubyforge_project:
|
114
|
+
rubygems_version: 2.0.3
|
115
|
+
signing_key:
|
116
|
+
specification_version: 4
|
117
|
+
summary: RubyGems plugin to allow a gem's compiled extension to be pre-built and cached
|
118
|
+
test_files:
|
119
|
+
- features/installing_with_cache.feature
|
120
|
+
- features/precompiling_gems.feature
|
121
|
+
- features/steps/command_steps.rb
|
122
|
+
- features/steps/file_steps.rb
|
123
|
+
- features/steps/rubygem_steps.rb
|
124
|
+
- spec/fixtures/gem-sources.tar.gz
|