/
gem.rb
162 lines (139 loc) · 5.18 KB
/
gem.rb
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
require "fpm/namespace"
require "fpm/source"
require "rubygems/package"
require "rubygems"
require "fileutils"
require "fpm/util"
class FPM::Source::Gem < FPM::Source
def self.flags(opts, settings)
settings.source[:gem] = "gem"
opts.on("--bin-path DIRECTORY",
"The directory to install gem executables") do |path|
settings.source[:bin_path] = path
end
opts.on("--package-prefix PREFIX",
"Prefix for gem packages") do |package_prefix|
settings.source[:package_prefix] = package_prefix
end
opts.on("--gem PATH_TO_GEM",
"The path to the 'gem' tool (defaults to 'gem' and searches " \
"your $PATH)") do |path|
settings.source[:gem] = path
end
end # def flags
def get_source(params)
gem = @paths.first
looks_like_name_re = /^[A-Za-z0-9_-]+$/
if !File.exists?(gem)
if gem =~ looks_like_name_re
download(gem, params[:version])
else
raise "Path '#{gem}' is not a file and does not appear to be the name of a rubygem."
end
end
end # def get_source
def can_recurse_dependencies
true
end
def download(gem_name, version=nil)
# This code mostly mutated from rubygem's fetch_command.rb
# Code use permissible by rubygems's "GPL or these conditions below"
# http://rubygems.rubyforge.org/rubygems-update/LICENSE_txt.html
puts "Trying to download #{gem_name} (version=#{version || 'latest'})"
dep = ::Gem::Dependency.new gem_name, version
# How to handle prerelease? Some extra magic options?
#dep.prerelease = options[:prerelease]
if ::Gem::SpecFetcher.fetcher.respond_to?(:fetch_with_errors)
specs_and_sources, errors =
::Gem::SpecFetcher.fetcher.fetch_with_errors(dep, true, true, false)
else
specs_and_sources =
::Gem::SpecFetcher.fetcher.fetch(dep, true)
errors = "???"
end
spec, source_uri = specs_and_sources.sort_by { |s,| s.version }.last
if spec.nil? then
raise "Invalid gem? Name: #{gem_name}, Version: #{version}, Errors: #{errors}"
end
path = ::Gem::RemoteFetcher.fetcher.download spec, source_uri
FileUtils.mv path, spec.file_name
@paths = [spec.file_name]
end
def get_metadata
File.open(@paths.first, 'r') do |f|
::Gem::Package.open(f, 'r') do |gem|
spec = gem.metadata
%w(
description
license
summary
version
).each do |field|
self[field.to_sym] = spec.send(field) rescue "unknown"
end
if self[:settings][:package_prefix]
self[:package_prefix] = self[:settings][:package_prefix]
else
self[:package_prefix] = "rubygem"
end
self[:name] = "#{self[:package_prefix]}#{self[:suffix]}-#{spec.name}"
self[:maintainer] = spec.author
self[:url] = spec.homepage
# TODO [Jay]: this will be different for different
# package managers. Need to decide how to handle this.
self[:category] = 'Languages/Development/Ruby'
# if the gemspec has extensions defined, then this should be a 'native' arch.
if !spec.extensions.empty?
self[:architecture] = "native"
else
self[:architecture] = "all"
end
# make sure we have a description
descriptions = [ self[:description], self[:summary], "#{spec.name} - no description given" ]
self[:description] = descriptions.detect { |d| !(d.nil? or d.strip.empty?) }
self[:dependencies] = []
spec.runtime_dependencies.map do |dep|
# rubygems 1.3.5 doesn't have 'Gem::Dependency#requirement'
if dep.respond_to?(:requirement)
reqs = dep.requirement.to_s.gsub(/,/, '')
else
reqs = dep.version_requirements
end
# Some reqs can be ">= a, < b" versions, let's handle that.
reqs.to_s.split(/, */).each do |req|
self[:dependencies] << "#{self[:package_prefix]}#{self[:suffix]}-#{dep.name} #{req}"
end
end # runtime_dependencies
end # ::Gem::Package
end # File.open (the gem)
end # def get_metadata
def make_tarball!(tar_path, builddir)
tmpdir = "#{tar_path}.dir"
gem = @paths.first
if self[:prefix]
installdir = "#{tmpdir}/#{self[:prefix]}"
# TODO(sissel): Overwriting @paths is bad mojo and confusing...
# Maybe we shouldn't?
@paths = [ self[:prefix] ]
else
installdir = File.join(tmpdir, ::Gem::dir)
@paths = [ ::Gem::dir ]
end
::FileUtils.mkdir_p(installdir)
args = [self[:settings][:gem], "install", "--quiet", "--no-ri", "--no-rdoc",
"--install-dir", installdir, "--ignore-dependencies", "-E"]
if self[:settings][:bin_path]
tmp_bin_path = File.join(tmpdir, self[:settings][:bin_path])
args += ["--bindir", tmp_bin_path]
@paths << self[:settings][:bin_path]
FileUtils.mkdir_p(tmp_bin_path) # Fixes #27
end
args << gem
safesystem(*args)
# make paths relative (/foo becomes ./foo)
tar(tar_path, @paths.collect {|p| ".#{p}"}, tmpdir)
FileUtils.rm_r(tmpdir)
# TODO(sissel): Make a helper method.
safesystem(*["gzip", "-f", tar_path])
end
end # class FPM::Source::Gem