def install(self, transaction):
        'Install rpm packages given a dictionary of packages.'

        # Check that all packages are available.
        if (len(transaction) < 1) or not transaction:
            raise ex.install_error, "unrecogniced transaction format."
        missingfiles = []
        for package in transaction.values():
            if not package.has_key('localfilename'):
                msg = "%s has no 'localfilename'" %package['name']
                missingfiles.append(msg)
                continue
            if not os.path.isfile(package['localfilename']):
                missingfiles.append(package['localfilename'])
        if len(missingfiles) > 0:
            raise ex.install_error("Missing files",missingfiles)

        if self.oldrpm:
            ts = rpm.TransactionSet(self.root, self.db)
        else:
            ts = rpm.TransactionSet(self.root)
            ts.setVSFlags(~(rpm.RPMVSF_NODSA|rpm.RPMVSF_NORSA))

        self.filenames = {}
        self.modes = {}
        ts_names = []

        for package in transaction.values():
            if package['flag'] == "upgrade":
                transactionmode = "u"
            elif package['flag'] == "install":
                transactionmode = "i"
            else:
                errmsg = "Mode '%s' for package '%s' not recognized." \
                      % (package['flag'], package['name'])
                raise ex.install_error(errmsg)
            fd = os.open(package['localfilename'], os.O_RDONLY)
            try:
                if self.oldrpm:
                    hdr = rpm.headerFromPackage(fd)[0]
                else:
                    headerts = rpm.TransactionSet(self.root)
                    headerts.setVSFlags(~(rpm.RPMVSF_NODSA|rpm.RPMVSF_NORSA))
                    hdr = headerts.hdrFromFdno(fd)
            except rpm.error, e:
                if str(e) == 'public key not available':
                    self.log.write_stdout('\nThe public key associated with this package was not found.\n\n')
          
            self.filenames[hdr[rpm.RPMTAG_NAME]] = package['localfilename']
            self.modes[hdr[rpm.RPMTAG_NAME]] = package['flag']
            os.close(fd)
            if self.oldrpm:
                ts.add(hdr, hdr, transactionmode)
            else:
                #RPM>=4.1 needs this
                ts.addInstall(hdr, hdr, transactionmode)
            ts_names.append(package['name'])
    def erase(self, packagenames):
        'Erase packages.'

        if self.oldrpm:
            names = ""
            for package in packagenames:
                names = package + " " + names
            command = "rpm -e %s\n" %names
            fd = os.popen(command)
            output = fd.read()
            exitval = fd.close()
            if exitval:
                message = "Error while removing packages:\n" +\
                    "Exitcode: %s\nOutput: %s\n\n" %(exitval, output)
                sys.stderr.write(message)
            return None
        else:
            ts = rpm.TransactionSet(self.root)
            ts.setVSFlags(~(rpm.RPMVSF_NODSA|rpm.RPMVSF_NORSA))

        ts_names = ""
        for package in packagenames:
            ts_names += package + ' '
            try:
                ts.addErase(package)
            except rpm.error:
                raise ex.not_installed_error, package
        deps = ts.check()
        if deps:
            deps_message = ""
            for ((name, version, release), (reqname, reqversion),
                 flags, suggest, sense) in deps:
                if sense == rpm.RPMDEP_SENSE_REQUIRES:
                    if reqversion == "" or reqversion == None:
                        deps_message += \
                            "\t'%s' requires '%s'.\n" % \
                            (name, reqname)
                    else:
                        deps_message += \
                            "\t'%s' requires '%s' version '%s'.\n"% \
                            (name, reqname, reqversion)
            raise ex.erase_error, \
                ":\n\t%s\n%s\n" % (ts_names, deps_message) \
        # Erase the rpms
        errors = ts.run(self._erase_callback, '')
        if errors:
            error_description = "RPM: "
            for error in errors:
                error_description = error_description + str(error[0]) + "\n"
            raise ex.install_error(error_description, ts_names)
            deps = ts.check()
        ts.order()
        if deps:
            deps_message = ""
            for ((name, version, release), (reqname, reqversion),
                 flags, suggest, sense) in deps:
                if sense == rpm.RPMDEP_SENSE_REQUIRES:
                    if reqversion == "" or reqversion == None:
                        deps_message +=  \
                            "\tPackage '%s' requires '%s'.\n" % \
                            (name, reqname)
                    else:
                        deps_message += \
                            "\tPackage '%s' requires '%s' version '%s'.\n"% \
                            (name, reqname, reqversion)
            raise ex.install_error(deps_message,ts_names)
        #
        # FIXME: Check for local conflicts and give nice output like the 
        # above dep check. This is interesting because of possible file
        # conflicts filling the console, thus making it hard to see the
        # real problem....
        #


        
        # Install the rpms
        if self.oldrpm:
            errors = ts.run(0, 0, self._install_callback, '')
        else:
            #RPM>=4.1 needs this
            errors = ts.run(self._install_callback, '')