rpgem 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/bin/rpgem +108 -0
  2. data/lib/rpgem.rb +177 -0
  3. data/lib/template.spec.erb +72 -0
  4. metadata +84 -0
data/bin/rpgem ADDED
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require File.expand_path(File.join(File.dirname(__FILE__),'..','lib','rpgem'))
5
+ require 'optparse'
6
+
7
+ options = {}
8
+ OptionParser.new do |opts|
9
+ opts.banner = <<-banner.split($/).map { |l| l.strip }.join($/)
10
+ Usage: rpgem gem_name [OPTIONS]
11
+ if no action is specified (-f, -s, -b), then all three will
12
+ be performed in that order.
13
+ banner
14
+
15
+ opts.on('-v VER',
16
+ '--version VER',
17
+ "Specify a specific gem version"
18
+ ) do |v|
19
+ options[:version] = v
20
+ end
21
+
22
+ opts.on('-V VER',
23
+ '--version-req VER',
24
+ "Specify a fuzzy version (i.e. '> 4.0')"
25
+ ) do |v|
26
+ options[:version_reqs] ||= []
27
+ options[:version_reqs] << v
28
+ end
29
+
30
+ opts.on('-R',
31
+ '--recursive',
32
+ "Recursively rpgem the dependencies"
33
+ ) do
34
+ options[:recursive] = true
35
+ end
36
+
37
+ opts.on('-f',
38
+ '--fetch',
39
+ "Fetch the gem"
40
+ ) do
41
+ options[:action] = :fetch!
42
+ end
43
+
44
+ opts.on('-s',
45
+ '--make-spec',
46
+ "Make the rpm specfile"
47
+ ) do
48
+ options[:action] = :make_spec!
49
+ end
50
+
51
+ opts.on('-b',
52
+ '--build',
53
+ "Build the rpm (this is the default)"
54
+ ) do
55
+ options[:action] = :build!
56
+ end
57
+
58
+ opts.on('-p PREFIX',
59
+ '--prefix PREFIX',
60
+ 'Specify a prefix to use during the install. Default: /usr'
61
+ ) do |p|
62
+ options[:prefix] = p.chomp('/')
63
+ end
64
+
65
+ opts.on('-d DEPENDS',
66
+ '--depends DEPENDS',
67
+ 'Specify a non-gem dependency (e.g. mysql-devel, etc.)'
68
+ ) do |d|
69
+ options[:dependencies] ||= []
70
+ options[:dependencies] << d
71
+ end
72
+ end.parse!
73
+
74
+ options.rmerge!({
75
+ :version => nil,
76
+ :recursive => false,
77
+ :version_reqs => [],
78
+ :action => :build!,
79
+ :ruby_cmd => "ruby",
80
+ :prefix => '/usr',
81
+ :dependencies => []
82
+ })
83
+
84
+ p [options, ARGV]
85
+
86
+ FileUtils.mkdir RPGem::TMP unless File.directory? RPGem::TMP
87
+
88
+ unless File.directory? RPGem::RPMBUILD_DIR
89
+ FileUtils.mkdir RPGem::RPMBUILD_DIR
90
+ FileUtils.in_dir RPGem::RPMBUILD_DIR do
91
+ FileUtils.mkdir "SOURCES"
92
+ FileUtils.mkdir "SPECS"
93
+ end
94
+ end
95
+
96
+ g = RPGem.new(ARGV[0], options)
97
+ g.fetch!
98
+ if options[:recursive]
99
+ g.recurse!(options[:action])
100
+ end
101
+ g.send(options[:action]) unless options[:action] == :fetch!
102
+
103
+
104
+ rescue Exception => e
105
+ puts e.to_s
106
+ puts e.backtrace
107
+ exit! 1
108
+ end
data/lib/rpgem.rb ADDED
@@ -0,0 +1,177 @@
1
+ require 'fileutils'
2
+ require 'rubygems'
3
+ require 'rubygems/format'
4
+ require 'erb'
5
+
6
+ module FileUtils
7
+ def self.in_dir(dir)
8
+ cwd = `pwd`.strip
9
+ cd dir
10
+ r = yield
11
+ cd cwd
12
+ r
13
+ end
14
+ end
15
+
16
+ class Hash
17
+ # like merge!, but doesn't update existing keys.
18
+ # useful for defaulting options
19
+ def rmerge!(hsh)
20
+ hsh.each do |k,v|
21
+ self[k] = v unless self.has_key? k
22
+ end
23
+ self
24
+ end
25
+
26
+ def rmerge(hsh)
27
+ self.dup.rmerge!(hsh)
28
+ end
29
+ end
30
+
31
+ class << File
32
+ def write(fname, str)
33
+ self.open(fname, "w") do |f|
34
+ f.write str
35
+ end
36
+ end
37
+ end
38
+
39
+ LIB_DIR = File.expand_path(File.dirname(__FILE__))
40
+
41
+
42
+ class RPGem
43
+ HOME_DIR = `echo ~`.strip
44
+ CWD = `pwd`.strip
45
+ TMP = "/tmp/rpgem"
46
+ RPMBUILD_DIR = "#{HOME_DIR}/rpmbuild"
47
+ SOURCES_DIR = "#{RPMBUILD_DIR}/SOURCES"
48
+ SPECS_DIR = "#{RPMBUILD_DIR}/SPECS"
49
+
50
+ def initialize(name, options={})
51
+ @name = name
52
+ @options = options.rmerge({
53
+ :version => nil,
54
+ :version_reqs => [],
55
+ :recursive => false,
56
+ :ruby_cmd => "ruby",
57
+ :dependencies => []
58
+ })
59
+ @options.each do |k,v|
60
+ instance_variable_set("@#{k}", v)
61
+ end
62
+ end
63
+
64
+ def sh_version_reqs
65
+ @version_reqs.map do |r|
66
+ "--version '#{r}'"
67
+ end.join ' '
68
+ end
69
+
70
+ attr_reader :name, :version
71
+
72
+ def to_s
73
+ if @version.nil?
74
+ @name
75
+ else
76
+ "#{@name}-#{@version}"
77
+ end
78
+ end
79
+
80
+ def gem_loc
81
+ "#{SOURCES_DIR}/#{self.to_s}.gem"
82
+ end
83
+
84
+ def spec_loc
85
+ "#{SPECS_DIR}/rpgem-#{self.to_s}.spec"
86
+ end
87
+
88
+ def format
89
+ @format ||= Gem::Format.from_file_by_path(gem_loc)
90
+ end
91
+
92
+ def spec
93
+ @spec ||= format.spec
94
+ end
95
+
96
+ def fetched_version(name_or_dep, requirements=[])
97
+ if name_or_dep.is_a? Gem::Dependency
98
+ d = name_or_dep
99
+ else
100
+ d = Gem::Dependency.new(name_or_dep, requirements)
101
+ end
102
+
103
+ currents = `ls #{SOURCES_DIR} | grep '^#{d.name}'`.split($/)
104
+ return nil if currents.empty?
105
+
106
+ currents.each do |c|
107
+ ver = c.match(/-(\d+(\.\d+)+)(\.gem)?$/)[1]
108
+ return ver if d.match?(d.name, ver)
109
+ end
110
+ return nil
111
+ end
112
+
113
+ def fetched?
114
+ return File.exists?(self.gem_loc)
115
+ end
116
+
117
+ def fetch!
118
+ v = self.fetched_version(@name, @version_reqs)
119
+ if (@version.nil? && v) || (!@version.nil? && self.fetched?)
120
+ @version = v
121
+ puts "Skipping fetch of #{self.to_s}"
122
+ else
123
+ puts "Fetching the gem #{self.to_s}"
124
+ if @version.nil?
125
+ system("rm -rf #{TMP}")
126
+ system("mkdir #{TMP}")
127
+ FileUtils.in_dir TMP do
128
+ system("gem fetch #{@name} #{sh_version_reqs}")
129
+ gem_title = `ls`
130
+ @version = gem_title.match(/-(\d+(\.\d+)+)\.gem$/)[1]
131
+ end
132
+ system("mv #{TMP}/* #{SOURCES_DIR}/")
133
+ else
134
+ FileUtils.in_dir SOURCES_DIR do
135
+ system("gem fetch #{@name} --version #{@version}")
136
+ end
137
+ end
138
+ end
139
+ end
140
+
141
+ def make_spec!
142
+ puts "rendering the specfile..."
143
+ template = File.read("#{LIB_DIR}/template.spec.erb")
144
+ specfile = ERB.new(template).result(binding)
145
+ puts "rendered:"
146
+ puts "==============="
147
+ puts specfile
148
+ puts "==============="
149
+ File.write(spec_loc, specfile)
150
+ puts "rendered to #{spec_loc}"
151
+ end
152
+
153
+ def build!
154
+ make_spec!
155
+ puts "-*- Building RPM -*-"
156
+ FileUtils.in_dir RPMBUILD_DIR do
157
+ system("rpmbuild -ba #{spec_loc}")
158
+ end
159
+ puts "-*- Done Building RPM -*-"
160
+ end
161
+
162
+ def recurse!(action=:setup!)
163
+ #TODO: add an option for dev dependencies
164
+ #TODO: don't choke on circular dependencies
165
+ deps = self.spec.runtime_dependencies
166
+ deps.each do |d|
167
+ g = self.class.new(d.name,
168
+ :version_reqs => d.requirements_list,
169
+ :recursive => true,
170
+ :ruby_cmd => @ruby_cmd
171
+ )
172
+ g.fetch!
173
+ g.recurse!(action)
174
+ g.send(action) unless action == :fetch!
175
+ end
176
+ end
177
+ end
@@ -0,0 +1,72 @@
1
+ <%
2
+ ruby_ver = begin
3
+ v = spec.required_ruby_version.to_s
4
+ v == ">= 0" ? "" : " #{v}"
5
+ end
6
+ rubygems_ver = begin
7
+ v = spec.required_rubygems_version.to_s
8
+ v == ">= 0" ? "" : " #{v}"
9
+ end
10
+
11
+ %>
12
+ %define rbname <%= spec.name %>
13
+
14
+ Name: rpgem-%{rbname}
15
+ Version: <%= spec.version.to_s %>
16
+ Release: 1%{?dist}
17
+ Summary: <%= spec.summary || spec.description %>
18
+
19
+ Group: Development/Languages/Ruby
20
+ License: <%= spec.license || "#FIXME - this gem has an unspecified license!" %>
21
+ URL: <%= spec.homepage %>
22
+ Source0: %{_sourcedir}/%{rbname}-%{version}.gem
23
+ BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
24
+ Vendor: <%= spec.author %>
25
+
26
+ BuildRequires: ruby<%=ruby_ver%>, rubygems<%=rubygems_ver%>
27
+ Requires: ruby<%=ruby_ver%>, rubygems<%=rubygems_ver%><%=
28
+ spec.runtime_dependencies.map do |d|
29
+ ", rpgem-#{d.name} #{d.requirements_list.first.gsub(/~>/,'>=')}"
30
+ end.join
31
+ %><%=
32
+ @dependencies.map {|d| ", #{d}"}.join
33
+ %>
34
+
35
+ Prefix: <%=@prefix%>
36
+
37
+ %define gem_prefix %{prefix}/lib/gems/%(%{prefix}/bin/ruby -e "puts VERSION.split('.')[0..1].join('.')")
38
+
39
+ %description
40
+ <%= spec.description %>
41
+
42
+ %prep
43
+ #noop
44
+
45
+ %build
46
+ rm -rf $RPM_BUILD_ROOT
47
+ mkdir $RPM_BUILD_ROOT
48
+ %{prefix}/bin/gem install %{SOURCE0} --force --local --no-rdoc --no-ri --install-dir=.
49
+
50
+ %install
51
+
52
+ echo %{gem_prefix}
53
+ rm -rf $RPM_BUILD_ROOT%{gem_prefix}
54
+ mkdir -p $RPM_BUILD_ROOT%{gem_prefix}
55
+ mv * $RPM_BUILD_ROOT%{gem_prefix}
56
+ chmod -R 0755 $RPM_BUILD_ROOT%{gem_prefix}
57
+
58
+ %clean
59
+ rm -rf $RPM_BUILD_ROOT
60
+
61
+
62
+ %files
63
+ %defattr(-,root,root,-)
64
+ %{gem_prefix}/gems/%{rbname}-%{version}/
65
+ %{gem_prefix}/specifications/%{rbname}-%{version}.gemspec
66
+ %{gem_prefix}/cache/%{rbname}-%{version}.gem
67
+ <% spec.executables.each do |e| %>
68
+ %{gem_prefix}/bin/<%= e %>
69
+ <% end %>
70
+
71
+
72
+ %changelog
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rpgem
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 1
10
+ version: 0.1.1
11
+ platform: ruby
12
+ authors:
13
+ - Jay Adkisson
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-05-17 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: erubis
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ description: RPGem will create a binary RPM with the compiled extensions, which you can install on a machine painlessly.
36
+ email: jay@causes.com
37
+ executables:
38
+ - rpgem
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - lib/rpgem.rb
45
+ - lib/template.spec.erb
46
+ - bin/rpgem
47
+ has_rdoc: true
48
+ homepage: http://github.com/jayferd/rpgem
49
+ licenses:
50
+ - MIT
51
+ post_install_message:
52
+ rdoc_options: []
53
+
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 23
71
+ segments:
72
+ - 1
73
+ - 3
74
+ - 6
75
+ version: 1.3.6
76
+ requirements:
77
+ - rpmbuild
78
+ rubyforge_project:
79
+ rubygems_version: 1.3.7
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: A gem-to-rpm converter, done right.
83
+ test_files: []
84
+