Show emerge command if --verbose is set
[g-gem.git] / g-gem.rb
blob5c84c6651609b1543db3cde9fbbf035389f85339
1 require 'portage'
2 require 'depatom'
3 require 'ebuild'
5 module GGem
6   @@gri = nil
7   @@sources = nil
9   SHORTMAP = {
10     'p' => :pretend,
11     'h' => :help,
12     'v' => :verbose,
13   }
14   
15   LONGMAP = {
16     'prepend' => :pretend,
17     'verbose' => :verbose,
18     'help' => :help,
19     'generate' => :generate,
20     'madgen' => :mass_generate,
21   }
23   SPECIAL_MAPS = {
24     'BlueCloth' => 'bluecloth',
25     'KirbyBase' => 'kirbybase',
26     'libxml-ruby' => 'libxml',
27     'RedCloth' => 'redcloth',
28     'mega' => 'mega-modules',
29     'nano' => 'nano-methods',
30     'gettext' => 'ruby-gettext',
31     'snmp' => 'snmplib',
32     'ZenTest' => 'zentest',
33     'NGSLib-RFile' => 'ngslib-rfile',
34     'tRuTag' => 'trutag',
35   }
37   class << self
39     attr_accessor :options
41     def main
42       @options, packages = parse_opts(ARGV)
43       Portage.setup_overlay(options[:pretend] || options[:mass_generate])
45       if options[:mass_generate] == true
46         mass_generate
47         puts "Ebuilds are in #{Portage.rubydev_overlay}"
48         return
49       end
51       spec_groups = packages.map {|pkg| get_specs(pkg)}
52       all_specs = spec_groups.flatten
53       if all_specs.empty?
54         puts "No package found"
55         return
56       end
58       ebuilds = []
59       for spec in all_specs
60         puts "Create ebuild for #{spec.full_name}" if options[:verbose]
61         gem_ebuild = Ebuild.new(spec)
62         gem_ebuild.write
63         ebuilds << gem_ebuild
64       end
65       # No prepend, digest the ebuilds
66       if options[:pretend] == false
67         ebuilds.each {|ebuild| ebuild.execute('digest')}
68       end
69       # don't specify --generate, continue digest and emerge
70       if options[:generate] == false 
71         cmd = 'emerge '+ARGV.join(' ')
72         puts cmd if options[:verbose]
73         system(cmd)
74       end
76       # don't clean up if --generate because overlay may be /tmp/*
77       if options[:generate] == true
78         puts "Ebuilds are in #{Portage.rubydev_overlay}"
79       else
80         Portage.cleanup
81       end
82     end
84     def get_specs(pkg)
85       specs = []
86       navigate(pkg.package_name,pkg.gem_requirement) { |spec| specs << spec }
87       specs.reverse
88     end
90     def navigate(gem_name,gem_version = nil,&block)
91       if Portage.ebuild_exists(gem_name,gem_version)
92         puts "Ebuild for #{gem_name} exists" if options[:verbose]
93         return true 
94       end
95       # cache source_index_hash, no need to recheck it everytime
96       @@gri = Gem::RemoteInstaller.new if @@gri.nil?
97       @@sources = @@gri.source_index_hash if @@sources.nil?
98       version_requirement = gem_version.is_a?(Gem::Version::Requirement) ? gem_version : Gem::Version::Requirement.new(gem_version || ">= 0")
99       gem_spec = nil
100       for source_name,source in @@sources
101         specs = source.find_name(gem_name, version_requirement)
102         next if specs.nil? or specs.empty?
103         # ignore mswin32 platform
104         satisfied_specs = specs.find_all do |spec|
105           spec.platform == 'ruby' and
106             version_requirement.satisfied_by?(spec.version)
107         end
108         gem_spec = satisfied_specs[-1]
109         class << gem_spec
110           def local?() false; end
111           def set_source(source)
112             @source = source
113           end
114           def fetched_from
115             @source
116           end
117         end
118         gem_spec.set_source(source_name)
119         break
120       end
121       if gem_spec.nil?
122         puts "#{gem_name} not found"
123         return false
124       end
125       yield(gem_spec)
126       for dep in gem_spec.dependencies
127         navigate(dep.name, dep.requirement_list, &block)
128       end
129       true
130     end
132     def parse_opts(argv)
133       opts = {
134         :pretend => false,
135         :generate => false,
136         :help => false,
137         :verbose => false,
138         :mass_generate => false
139       }
140       packages = []
141     
142       for arg in argv
143         if arg =~ /^-[^-]/
144           for i in 1..arg.length-1
145             if SHORTMAP.key? arg[i..i]
146               opts[SHORTMAP[arg[i..i]]] = true
147             else
148               puts "Unknown option '-#{arg[i..i]}'"
149             end
150           end
151         elsif arg =~ /^--/
152           if LONGMAP.key? arg[2..-1]
153             opts[LONGMAP[arg[2..-1]]] = true
154           else
155             puts "Unknown option '#{arg}'"
156           end
157         else
158           packages << DependencyAtom.new(arg)
159         end
160       end
161       return opts, packages
162     end
164     def mass_generate
165       @@gri = Gem::RemoteInstaller.new if @@gri.nil?
166       @@sources = @@gri.source_index_hash if @@sources.nil?
167       for source_name,source in @@sources
168         source.each do |full_name,spec|
169           if spec.platform == 'ruby'
170             puts full_name
171             class << spec
172               def local?() false; end
173               def set_source(source) @source = source end
174               def fetched_from() @source end
175             end
176             spec.set_source(source_name)
177             e = Ebuild.new(spec)
178             e.write
179           end
180         end
181       end
182     end
184     def ebuild_name(gem_name)
185       return SPECIAL_MAPS[gem_name] if SPECIAL_MAPS.key? gem_name
186       # Remove punctation
187       gem_name.gsub(/[_:.]+/,'-').
188         gsub(/([^-0-9A-Z])([A-Z])([a-z])/) { "#{$1}-#{$2}#{$3}" }. # split words
189         gsub(/([^-0-9A-Z])([A-Z])([a-z])/) { "#{$1}-#{$2}#{$3}" }. # split words again
190         gsub(/([A-Z]{2,})([A-Z][^A-Z-])/) { "#{$1}-#{$2}"}. # find acronyms
191         gsub(/([A-Z]{2,})-([A-Z])$/) {"#{$1}#{$2}"}. # recover wrong acronym breaking
192         downcase
193     end
194   end