--madgen should write in /tmp overlay as it may overwrite existing ebuilds
[g-gem.git] / g-gem.rb
blobaf68cd2284b6593f33b2cd379f79524da4817154
1 require 'portage'
2 require 'depatom'
3 require 'ebuild'
5 module GGem
6   @@gri = nil
7   @@sources = nil
9   SHORTMAP = {
10     'p' => :prepend,
11     'h' => :help,
12     'v' => :verbose,
13   }
14   
15   LONGMAP = {
16     'prepend' => :prepend,
17     'verbose' => :verbose,
18     'help' => :help,
19     'generate' => :generate,
20     'madgen' => :mass_generate,
21   }
23   class << self
25     attr_accessor :options
27     def main
28       @options, packages = parse_opts(ARGV)
29       Portage.setup_overlay(options[:prepend] || options[:mass_generate])
31       if options[:mass_generate] == true
32         mass_generate
33         puts "Ebuilds are in #{Portage.rubydev_overlay}"
34         return
35       end
37       spec_groups = packages.map {|pkg| get_specs(pkg)}
38       all_specs = spec_groups.flatten
40       ebuilds = []
41       for spec in all_specs
42         puts "Create ebuild for #{spec.full_name}" if options[:verbose]
43         gem_ebuild = Ebuild.new(spec)
44         gem_ebuild.write
45         ebuilds << gem_ebuild
46       end
47       # No prepend, digest the ebuilds
48       if options[:prepend] == false
49         ebuilds.each {|ebuild| ebuild.execute('digest')}
50       end
51       # don't specify --generate, continue digest and emerge
52       if options[:generate] == false 
53         system('emerge '+ARGV.join(' ')) 
54       end
56       # don't clean up if --generate because overlay may be /tmp/*
57       if options[:generate] == true
58         puts "Ebuilds are in #{Portage.rubydev_overlay}"
59       else
60         Portage.cleanup
61       end
62     end
64     def get_specs(pkg)
65       specs = []
66       navigate(pkg.package_name,pkg.gem_requirement) { |spec| specs << spec }
67       specs.reverse
68     end
70     def navigate(gem_name,gem_version = nil,&block)
71       if Portage.ebuild_exists(gem_name,gem_version)
72         puts "Ebuild for #{gem_name} exists" if options[:verbose]
73         return true 
74       end
75       # cache source_index_hash, no need to recheck it everytime
76       @@gri = Gem::RemoteInstaller.new if @@gri.nil?
77       @@sources = @@gri.source_index_hash if @@sources.nil?
78       version_requirement = gem_version.is_a?(Gem::Version::Requirement) ? gem_version : Gem::Version::Requirement.new(gem_version || ">= 0")
79       gem_spec = nil
80       for source_name,source in @@sources
81         specs = source.find_name(gem_name, version_requirement)
82         next if specs.nil? or specs.empty?
83         # ignore mswin32 platform
84         satisfied_specs = specs.find_all do |spec|
85           spec.platform == 'ruby' and
86             version_requirement.satisfied_by?(spec.version)
87         end
88         gem_spec = satisfied_specs[-1]
89         class << gem_spec
90           def local?() false; end
91           def set_source(source)
92             @source = source
93           end
94           def fetched_from
95             @source
96           end
97         end
98         gem_spec.set_source(source_name)
99         break
100       end
101       if gem_spec.nil?
102         puts "#{gem_name} not found"
103         return false
104       end
105       yield(gem_spec)
106       for dep in gem_spec.dependencies
107         navigate(dep.name, dep.requirement_list, &block)
108       end
109       true
110     end
112     def parse_opts(argv)
113       opts = {
114         :prepend => false,
115         :generate => false,
116         :help => false,
117         :verbose => false,
118         :mass_generate => false
119       }
120       packages = []
121     
122       for arg in argv
123         if arg =~ /^-[^-]/
124           for i in 1..arg.length-1
125             if SHORTMAP.key? arg[i..i]
126               opts[SHORTMAP[arg[i..i]]] = true
127             else
128               puts "Unknown option '-#{arg[i..i]}'"
129             end
130           end
131         elsif arg =~ /^--/
132           if LONGMAP.key? arg[2..-1]
133             opts[LONGMAP[arg[2..-1]]] = true
134           else
135             puts "Unknown option '#{arg}'"
136           end
137         else
138           packages << DependencyAtom.new(arg)
139         end
140       end
141       return opts, packages
142     end
144     def mass_generate
145       @@gri = Gem::RemoteInstaller.new if @@gri.nil?
146       @@sources = @@gri.source_index_hash if @@sources.nil?
147       for source_name,source in @@sources
148         source.each do |full_name,spec|
149           if spec.platform == 'ruby'
150             puts full_name
151             class << spec
152               def local?() false; end
153               def set_source(source) @source = source end
154               def fetched_from() @source end
155             end
156             spec.set_source(source_name)
157             e = Ebuild.new(spec)
158             e.write
159           end
160         end
161       end
162     end
163   end