sound/lame: Update to 3.100
[feed/packages.git] / lang / ruby / ruby_find_pkgsdeps
1 #!/usr/bin/ruby -Eutf-8
2 # encoding: utf-8
3 #
4 # Find dependencies between ruby packages
5 #
6 # Must run inside a openwrt with all *ruby* packages installed
7 #
8
9 RUBY_SIMPLE_VERSION = RUBY_VERSION.split(".")[0..1].join(".")
10 failed = false
11
12 puts "Looking for installed ruby packages..."
13 packages=`opkg list-installed '*ruby*' | cut -d' ' -f 1`.split("\n")
14
15 puts "Looking for packages files..."
16 package_files=Hash.new { |h,k| h[k]=[] }
17 packages.each do
18 |pkg|
19 files=`opkg files "#{pkg}" | sed -e 1d`.split("\n")
20 package_files[pkg]=files if files
21 end
22
23 require_regex=/^require ["']([^"']+)["'].*/
24 require_regex_ignore=/^require ([a-zA-Z\$]|["']$|.*\/$)/
25 require_ignore=%w{drb/invokemethod16 foo rubygems/defaults/operating_system win32console java Win32API
26 builder/xchar json/pure simplecov win32/sspi rdoc/markdown/literals_1_8 enumerator win32/resolv rbtree
27 nqxml/streamingparser nqxml/treeparser xmlscan/parser xmlscan/scanner xmltreebuilder xml/parser xmlparser xml/encoding-ja xmlencoding-ja
28 iconv uconv win32ole gettext/po_parser gettext/mo libxml psych.jar psych_jars jar-dependencies thread minitest/proveit}
29
30 builtin_enc=[
31 Encoding.find("ASCII-8BIT"),
32 Encoding.find("UTF-8"),
33 Encoding.find("UTF-7"),
34 Encoding.find("US-ASCII"),
35 ]
36
37 puts "Looking for requires in files..."
38 files_requires=Hash.new { |h,k| h[k]=[] }
39 packages.each do
40 |pkg|
41 package_files[pkg].each do
42 |file|
43 next if not File.file?(file)
44
45 if not file =~ /.rb$/
46 if File.executable?(file)
47 magic=`head -c50 '#{file}' | head -1`
48 begin
49 if not magic =~ /ruby/
50 next
51 end
52 rescue
53 next
54 end
55 else
56 next
57 end
58 end
59 #puts "Checking #{file}..."
60 File.open(file, "r") do
61 |f|
62 lineno=0
63 while line=f.gets() do
64 lineno+=1; encs=[]; requires=[]; need_encdb=false
65
66 line=line.chomp.gsub!(/^[[:blank:]]*/,"")
67
68 case line
69 when /^#.*coding *:/
70 if lineno <= 2
71 enc=line.sub(/.*coding *: */,"").sub(/ .*/,"")
72 encs << Encoding.find(enc)
73 end
74 end
75 line.gsub!(/#.*/,"")
76 case line
77 when "__END__"
78 break
79 when /^require /
80 #puts "#{file}:#{line}"
81 if require_regex_ignore =~ line
82 #puts "Ignoring #{line} at #{file}:#{lineno} (REGEX)..."
83 next
84 end
85 if not require_regex =~ line
86 $stderr.puts "Unknown require: '#{line}' at file #{file}:#{lineno}"
87 failed=true
88 end
89 require=line.gsub(require_regex,"\\1")
90 require.gsub!(/\.(so|rb)$/,"")
91
92 if require_ignore.include?(require)
93 #puts "Ignoring #{line} at #{file}:#{lineno} (STR)..."
94 next
95 end
96
97 files_requires[file] += [require]
98
99 when /Encoding::/
100 encs=line.scan(/Encoding::[[:alnum:]_]+/).collect {|enc| eval(enc) }.select {|enc| enc.kind_of? Encoding }
101 need_encdb=true
102 end
103
104 next if encs.empty?
105 required_encs = (encs - builtin_enc).collect {|enc| "enc/#{enc.name.downcase.gsub("-","_")}" }
106 required_encs << "enc/encdb" if need_encdb
107
108 files_requires[file] += required_encs
109 end
110 end
111 end
112 end
113 exit(1) if failed
114
115 # Add deps from .so
116 package_files.each do |(pkg,files)| files.each do |file|
117 case file
118 when /\/nkf\.so$/
119 files_requires[file]= files_requires[file] + ["enc/encdb"]
120 end
121 end; end
122
123 puts "Grouping package requirements per package"
124 package_requires_files = Hash.new{|h,k| h[k] = Hash.new { |h2,k2| h2[k2] = [] } }
125 package_files.each do |(pkg,files)|
126 package_requires_files[pkg]
127 files.each do |file|
128 files_requires[file].each do |requires|
129 package_requires_files[pkg][requires] << file
130 end
131 end
132 end
133
134 weak_dependency=Hash.new { |h,k| h[k]=[] }
135 weak_dependency.merge!({
136 "ruby-misc"=>["ruby-openssl","ruby-fiddle"], #securerandom.rb
137 "ruby-debuglib"=>["ruby-readline"], #debug.rb
138 "ruby-drb"=>["ruby-openssl"], #drb/ssl.rb
139 "ruby-irb"=>["ruby-rdoc", "ruby-readline"], #irb/cmd/help.rb
140 "ruby-gems"=>["ruby-openssl","ruby-io-console","ruby-webrick"], #rubygems/commands/cert_command.rb rubygems/user_interaction.rb rubygems/server.rb
141 "ruby-mkmf"=>["ruby-webrick"], #un.rb
142 "ruby-net"=>["ruby-openssl","ruby-io-console","ruby-zlib"], #net/*.rb
143 "ruby-optparse"=>["ruby-uri","ruby-datetime"], #optparse/date.rb optparse/uri.rb
144 "ruby-rake"=>["ruby-net","ruby-gems"], #rake/contrib/ftptools.rb /usr/bin/rake
145 "ruby-rdoc"=>["ruby-gems","ruby-readline","ruby-webrick", #/usr/bin/rdoc and others
146 "ruby-io-console"], #rdoc/stats/normal.rb
147 "ruby-webrick"=>["ruby-openssl"], #webrick/ssl.rb
148 "ruby-testunit"=>["ruby-io-console"], #gems/test-unit-3.1.5/lib/test/unit/ui/console/testrunner.rb
149 })
150
151 puts "Preloading gems..."
152 Gem::Specification.all.each{ |x| gem x.name }
153
154 puts "Looking for package dependencies..."
155 package_provides = {}
156 package_dependencies = Hash.new { |h,k| h[k]=[] }
157 package_requires_files.each do
158 |(pkg,requires_files)|
159
160 requires_files.each do
161 |(require,files)|
162 if package_provides.include?(require)
163 found = package_provides[require]
164 else
165 found = package_files.detect {|(pkg,files)| files.detect {|file| $:.detect {|path| "#{path}/#{require}" == file.gsub(/\.(so|rb)$/,"") } } }
166 if not found
167 $stderr.puts "#{pkg}: Nothing provides #{require} for #{files.collect {|file| file.sub("/usr/lib/ruby/","") }.join(",")}"
168 failed = true
169 next
170 end
171 found = found.first
172 package_provides[require] = found
173 end
174 if weak_dependency[pkg].include?(found)
175 puts "#{pkg}: #{found} provides #{require} (weak depedendency ignored)"
176 else
177 puts "#{pkg}: #{found} provides #{require} for #{files.collect {|file| file.sub("/usr/lib/ruby/","") }.join(",")}"
178 package_dependencies[pkg] += [found]
179 end
180 end
181 end
182 if failed
183 puts "There is some missing requirements not mapped to files in packages."
184 puts "Please, fix the missing files or ignore them on require_ignore var"
185 exit(1)
186 end
187 # Remove self dependency
188 package_dependencies = Hash[package_dependencies.collect {|(pkg,deps)| [pkg,package_dependencies[pkg]=deps.uniq.sort - [pkg]]}]
189 package_dependencies.default = []
190
191 puts "Expanding dependencies..."
192 begin
193 changed=false
194 package_dependencies.each do
195 |(pkg,deps)|
196 next if deps.empty?
197 deps_new = deps.collect {|dep| [dep] + package_dependencies[dep] }.inject([],:+).uniq.sort
198 if not deps == deps_new
199 puts "#{pkg}: #{deps.join(",")}"
200 puts "#{pkg}: #{deps_new.join(",")}"
201 package_dependencies[pkg]=deps_new
202 changed=true
203 end
204 end
205 end if not changed
206
207 puts "Removing redundant dependencies..."
208 package_dependencies.each do
209 |(pkg,deps)|
210 package_dependencies[pkg]=deps.uniq - [pkg]
211 end
212
213 puts "Checking for mutual dependencies..."
214 package_dependencies.each do
215 |(pkg,deps)|
216 if deps.include? pkg
217 $stderr.puts "#{pkg}: Cycle dependency detected! "
218 failed = true
219 end
220 end
221 exit(1) if failed
222
223
224 package_dependencies2=package_dependencies.dup
225 package_dependencies.each do
226 |(pkg,deps)|
227
228 # Ignore dependencies that are already required by another dependency
229 deps_clean = deps.reject {|dep_suspect| deps.detect {|dep_provider|
230 if package_dependencies[dep_provider].include?(dep_suspect)
231 puts "#{pkg}: #{dep_suspect} is already required by #{dep_provider}"
232 true
233 end
234 } }
235
236 if not deps==deps_clean
237 puts "before: #{deps.join(",")}"
238 puts "after: #{deps_clean.join(",")}"
239 package_dependencies2[pkg]=deps_clean
240 end
241 end
242 package_dependencies=package_dependencies2
243
244 puts "Checking current packages dependencies..."
245 ok=true
246 package_dependencies.each do
247 |(pkg,deps)|
248 current_deps=`opkg depends #{pkg} | sed -r -e '1d;s/^[[:blank:]]*//'`.split("\n")
249 current_deps.reject!{|dep| dep =~ /^lib/ }
250 current_deps -= ["ruby"]
251
252 extra_dep = current_deps - deps
253 $stderr.puts "Package #{pkg} does not need to depend on #{extra_dep.join(" ")} " if not extra_dep.empty?
254 missing_dep = deps - current_deps
255 $stderr.puts "Package #{pkg} needs to depend on #{missing_dep.join(" ")} " if not missing_dep.empty?
256
257 if not extra_dep.empty? or not missing_dep.empty?
258 $stderr.puts "define Package/#{pkg}"
259 $stderr.puts " DEPENDS:=ruby#{([""] +deps).join(" +")}"
260 ok=false
261 end
262 end
263
264 puts "All dependencies are OK." if ok
265
266 __END__