#!/usr/bin/env python
# revdep-rebuild.py -- rebuild all packages with broken library dependencies

import os
import os.path
import subprocess

LDD = '/usr/bin/ldd'
NOTFOUND = 'not found'
DEBUG = False

class RevdepRebuild(object):
    "Rebuild all packages with broken library dependencies"

    def __init__(self, debug=DEBUG):
        self.debug = debug
        self.the_paths = self.paths()
        self.the_files = []
        
        for path in self.the_paths:
            self.the_files.extend(self.files(path))

        self.the_broken_files = filter(self.ldd_not_found, self.the_files)

        if self.debug: print "The broken files are: ", self.the_broken_files

        self.broken_packages = {}
        for f in self.the_broken_files:
            package = self.pathname_to_package(f)
            if package is not None:
                self.broken_packages[package] = True
        self.rebuild_packages = sorted(self.broken_packages.keys())

    def paths(self):
        return os.environ['PATH'].split(':')

    def files(self, path):
        files = sorted(os.listdir(path))
        files_with_path = map(lambda f: os.path.join(path, f), files)
        real_files = filter(os.path.isfile, files_with_path)
        return real_files

    def ldd_not_found(self, pathname):
        lines = subprocess.Popen([LDD, pathname], bufsize=1,
                                 stderr=open('/dev/null', 'w'),
                                 stdout=subprocess.PIPE).communicate()[0]
        for line in lines.split('\n'):
            # if self.debug: print "LDD(%s)=%s" % (pathname, line)
            
            if line.find(NOTFOUND) != -1:
                return True

        return False

    def pathname_to_package(self, pathname):
        lines = subprocess.Popen(['/usr/sbin/pkg_info', '-W', pathname],
                                 stdout=subprocess.PIPE).communicate()[0]
        for line in lines.split('\n'):
            if line.find('was installed by package') != -1:
                return line.split(' ')[-1]

        return None

if __name__ == '__main__':
    rr = RevdepRebuild(debug=True)
    print "Rebuild the following package: "
    print rr.rebuild_packages
