#!/usr/bin/python

#
# RpmDD removes packages which are considered duplicate (the same name and older version).
#
#    Program usage
#
# rpmdd [-s] [-d] [-v] ...
# -v   verbose
# -s   consider only source RPM files (non-source RPM files by default)
# -d   delete (do nothing by default)
#
#
#    Algorith description.
#
# Build hashtable with {name: (header, file name)}. If name exists as key, then
# compare package versions. Delete older one (if exists) and put newer one's header
# and file name as tuple into dictionary.
# 

import getopt                                                                                                                                                            
import os
import rpm
import sys

# Each packages hashtable value is a tuple with two elements.
# First element is package's header and second one is its file name.
HEADER = 0
FILE_NAME = 1


#
# default configuration values
#

# do not delete files
delete = False

# load only non-source RPM files
load_srpms = False

# verbose off
verbose = False


#
# process program arguments
#
optlist, args = getopt.getopt(sys.argv[1:], 'vsd')

for opt in optlist:
    if opt[0] == '-v':
        verbose = True

    if opt[0] == '-d':
        delete = True

    if opt[0] == '-s':
        load_srpms = True


#
# Let's do it.
#
packages = {}

for file_name in args:
    # load header
    fd = os.open(file_name, os.O_RDONLY)
    try:
        (header, is_source) = rpm.headerFromPackage(fd)
    except rpm.error:
        if verbose:
            print 'Skipping %s package. Loading RPM package\'s header error.' % (file_name) 
        os.close(fd)
        continue

    if header == None: # check if package is loaded successfully
        if verbose:
            print 'Skipping %s package. File is not RPM package.' % (file_name) 
        os.close(fd)
        continue

    os.close(fd)

    # delete only files with the same file type (source or non-source),
    # which is requested by user
    if (is_source and load_srpms) or (not is_source and not load_srpms): 
        name = header['name']


        if packages.has_key(name):        # we have found duplicate

            # compare version and 
            if rpm.versionCompare(header, packages[name][HEADER]):
                fn_to_del = packages[name][FILE_NAME]
                packages[name] = (header, file_name)
            else:
                fn_to_del = file_name

            if verbose:            # be verbose as requested
                print 'Removing %s' % (fn_to_del)

            if delete:            # delete if it has been really demanded
                os.remove(fn_to_del)

        else:
            # there is no duplicate, just save header and file name, so we
            # can compare with next packages
            packages[name] = (header, file_name)
