diff --git a/Library/Homebrew/cmd/bottle.rb b/Library/Homebrew/cmd/bottle.rb index 0fe7fb8367..04f2fb3efd 100644 --- a/Library/Homebrew/cmd/bottle.rb +++ b/Library/Homebrew/cmd/bottle.rb @@ -5,6 +5,8 @@ require 'keg' require 'cmd/versions' require 'utils/inreplace' require 'erb' +require 'open3' +require 'extend/pathname' class BottleMerger < Formula # This provides a URL and Version which are the only needed properties of @@ -42,7 +44,46 @@ module Homebrew extend self end def keg_contains string, keg - quiet_system 'fgrep', '--recursive', '--quiet', '--max-count=1', string, keg + if not ARGV.homebrew_developer? + return quiet_system 'fgrep', '--recursive', '--quiet', '--max-count=1', string, keg + end + + # Find all files that still reference the keg via a string search + keg_ref_files = `/usr/bin/fgrep --files-with-matches --recursive "#{string}" "#{keg}" 2>/dev/null` + keg_ref_files = (keg_ref_files.map{ |file| Pathname.new(file.strip) }).reject(&:symlink?) + + # If there are no files with that string found, return immediately + return false if keg_ref_files.empty? + + # Start printing out each file and any extra information we can find + opoo "String '#{string}' still exists in these files:" + keg_ref_files.each do |file| + puts "#{Tty.red}#{file}#{Tty.reset}" + + # If we can't use otool on this file, just skip to the next file + next if not file.mach_o_executable? and not file.mach_o_bundle? and not file.dylib? and not file.extname == '.a' + + # Get all libraries this file links to, then display only links to libraries that contain string in the path + linked_libraries = `otool -L "#{file}"`.split("\n").drop(1) + linked_libraries.map!{ |lib| lib.strip.split()[0] } + linked_libraries = linked_libraries.select{ |lib| lib.include? string } + + linked_libraries.each do |lib| + puts " #{Tty.gray}-->#{Tty.reset} links to #{lib}" + end + + # Use strings to search through the file for each string + strings = `strings -t x - "#{file}"`.select{ |str| str.include? string }.map{ |s| s.strip } + + # Don't bother reporting a string if it was found by otool + strings.reject!{ |str| linked_libraries.include? str.split[1] } + strings.each do |str| + offset, match = str.split + puts " #{Tty.gray}-->#{Tty.reset} match '#{match}' at offset #{Tty.em}0x#{offset}#{Tty.reset}" + end + end + puts + true end def bottle_output bottle