#!/usr/bin/python -tt
#---------------------------------------------------------------
# Project         : Mandriva Linux
# Module          : rpmlint
# File            : rpmdiff
# Version         : $Id: rpmdiff 1179 2006-05-16 21:02:07Z scop $
# Author          : Frederic Lepied
# Created On      : Sat Feb  9 21:24:33 2002
# Purpose         : rewriting of rpmdiff to show the use of the
#                   Pkg lib.
#---------------------------------------------------------------

import rpm
import sys
import os
import stat
import site
import getopt

if not os.path.exists('Pkg.py') and os.path.isdir("/usr/share/rpmlint"):
    site.addsitedir("/usr/share/rpmlint")

import Pkg

# constants

TAGS = [ (rpm.RPMTAG_NAME, 'NAME'),
         (rpm.RPMTAG_SUMMARY, 'SUMMARY'),
         (rpm.RPMTAG_DESCRIPTION, 'DESCRIPTION'),
         (rpm.RPMTAG_GROUP, 'GROUP'),
         (rpm.RPMTAG_LICENSE, 'LICENSE'),
         (rpm.RPMTAG_URL, 'URL'),
         (rpm.RPMTAG_PREIN, 'PREIN'),
         (rpm.RPMTAG_POSTIN, 'POSTIN'),
         (rpm.RPMTAG_PREUN, 'PREUN'),
         (rpm.RPMTAG_POSTUN, 'POSTUN'),
         ]

FILEIDX = [ ('S', 4),
            ('M', 0),
            ('5', 5),
            ('D', None),
            ('L', 3),
            ('U', 1),
            ('G', 2),
            (None, None),
            ]
FILEIDX_T = ('T', 6)

DEPFORMAT = '%-11s%s %s %s %s'
FORMAT = '%-11s%s'

ADDED   = 'added'
REMOVED = 'removed'
CHANGED = 'S.5....T'

# code starts here

# load a package from a file or from the installed ones
def load_pkg(name, tmpdir='/tmp'):
    st=os.stat(name)
    if stat.S_ISREG(st[stat.ST_MODE]):
        try:
            return Pkg.Pkg(name, tmpdir)
        except TypeError:
            pass
    return Pkg.InstalledPkg(name)

# output the right string according to RPMSENSE_* const
def sense2str(sense):
    s = ""
    if sense & rpm.RPMSENSE_LESS:
        s += "<"
    if sense & rpm.RPMSENSE_GREATER:
        s += ">"
    if sense & rpm.RPMSENSE_EQUAL:
        s += "="
    return s

# compares 2 lists
def cmp_list(o, n, name):
    for old in o:
        if not old in n:
            print DEPFORMAT % (REMOVED, name, old[0], sense2str(old[2]), old[1])
    for new in n:
        if not new in o:
            print DEPFORMAT % (ADDED, name, new[0], sense2str(new[2]), new[1])

# filter the own name of the package
def get_provides(pkg):
    name = pkg[rpm.RPMTAG_NAME]
    p = []
    for prov in pkg.provides():
        if not (prov[0] == name and prov[1] == '%s-%s' % (pkg[rpm.RPMTAG_VERSION], pkg[rpm.RPMTAG_RELEASE]) and prov[2] == rpm.RPMSENSE_EQUAL):
            p.append(prov)
    return p

def usage(exit=1):
    print "Usage: %s [<options>] <old package> <new package>" % sys.argv[0]
    print "Options:"
    print "  -h, --help            Output this message and exit"
    print "  -t, --ignore-times    Ignore differences in file timestamps"
    sys.exit(exit)

def main():
    ignore_times = False
    try:
        opts, args = getopt.getopt(sys.argv[1:], "ht", ["help", "ignore-times"])
    except getopt.GetoptError, e:
        print "Error: %s" % e
        usage()

    for option, argument in opts:
        if option in ("-h", "--help"):
            usage(0)
        if option in ("-t", "--ignore-times"):
            ignore_times = True

    if len(args) != 2:
        usage()

    if not ignore_times:
        FILEIDX[7] = FILEIDX_T

    old = load_pkg(args[0])
    new = load_pkg(args[1])

    old_files = old.files().keys()
    new_files = new.files().keys()
    files = old_files + new_files

    files.sort()
    previous = None

    for s in TAGS:
        old_tag = old[s[0]]
        new_tag = new[s[0]]
        if old_tag != new_tag:
            if old_tag == None:
                print FORMAT % (ADDED, s[1])
            elif new_tag == None:
                print FORMAT % (REMOVED, s[1])
            else:
                print FORMAT % ('S.5.....', s[1])

    cmp_list(old.prereq(), new.prereq(), 'PREREQ')
    cmp_list(old.requires(), new.requires(), 'REQUIRES')
    cmp_list(get_provides(old), get_provides(new), 'PROVIDES')
    cmp_list(old.conflicts(), new.conflicts(), 'CONFLICTS')

    old_files = old.files()
    new_files = new.files()

    for f in files:
        diff = 0
        if f == previous:
            continue
        previous = f
        try:
            old_file = old_files[f]
        except KeyError:
            old_file = None
        try:
            new_file = new_files[f]
        except KeyError:
            new_file = None

        if not old_file:
            print FORMAT % (ADDED, f)
        elif not new_file:
            print FORMAT % (REMOVED, f)
        else:
            format = ''
            for idx in range(0, len(FILEIDX)):
                entry = FILEIDX[idx]
                if entry[1] != None and old_file[entry[1]] != new_file[entry[1]]:
                    format = format + entry[0]
                    diff = 1
                else:
                    format = format + '.'
            if diff:
                print FORMAT % (format, f)

if __name__ == '__main__':
    main()

# rpmdiff ends here

# Local variables:
# indent-tabs-mode: nil
# py-indent-offset: 4
# End:
# ex: ts=4 sw=4 et
