lede-packages-rs

git clone git://archive.git.mtrnord.blog/MTRNord/lede-packages-rs.git
Log | Files | Refs | README | LICENSE

ruby_find_pkgsdeps (8095B)


      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__