Commit a1eb7c45 authored by Seblu's avatar Seblu
Browse files

Add diff command

parent 7de5cb42
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -149,6 +149,18 @@ def c_del(parser, args):
                raise Exception("Aborted!")
        repo.delete(img.name, img.version)

def c_diff(parser, args):
    '''
    Show diff between two repositories or images
    '''
    repoman = load_repositories(args)
    if args.object[0] in repoman.onlines and args.object[1] in repoman.onlines:
        Repository.diff(repoman[args.object[0]], repoman[args.object[1]])
    else:
        img1, repo1 = select_image(args.object[0], repoman, args.best)
        img2, repo2 = select_image(args.object[1], repoman, args.best)
        PackageImage.diff(img1, img2)

def c_extract(parser, args):
    '''
    Extract an image package inside a directory
@@ -357,6 +369,14 @@ p_del.add_argument("-f", "--force", action="store_true", default=False,
                   help="delete image without confirmation")
p_del.set_defaults(func=c_del)

# diff command parser
p_diff = subparsers.add_parser("diff", help=c_diff.__doc__.lower())
p_diff.add_argument("object", nargs=2,
                    help="object syntax is <path|repository|[repository/]image[:version]>")
p_diff.add_argument("-b", "--best", action="store_true", default=False,
                    help="in best mode, image is the most recent in all repositories")
p_diff.set_defaults(func=c_diff)

# extract command parser
p_extract = subparsers.add_parser("extract", help=c_extract.__doc__.lower())
p_extract.add_argument("-p", action="store_true", dest="payload", default=False,
+41 −1
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ import os
import stat
import time
import json
import difflib
import ConfigParser
import subprocess
import tarfile
@@ -351,6 +352,46 @@ class PackageImage(Image):
    Packaged image manipulation class
    '''

    @classmethod
    def diff(cls, pkg1, pkg2):
        '''
        Diff two packaged images
        '''
        arrow("Differnce from images #y#%s v%s#R# to #r#%s v%s#R#:" % (pkg1.name,
                                                                       pkg1.version,
                                                                       pkg2.name,
                                                                       pkg2.version))
        # Extract images for diff scripts files
        fromfiles = set(pkg1._tarball.getnames(re_pattern="(parser|setup)/.*"))
        tofiles = set(pkg2._tarball.getnames(re_pattern="(parser|setup)/.*"))
        for f in fromfiles | tofiles:
            # preparing from info
            if f in fromfiles:
                fromfile = os.path.join(pkg1.id, f)
                fromdata = pkg1._tarball.extractfile(f).readlines()
            else:
                fromfile = "/dev/null"
                fromdata = ""
            # preparing to info
            if f in tofiles:
                tofile = os.path.join(pkg2.id, f)
                todata = pkg2._tarball.extractfile(f).readlines()
            else:
                tofile = "/dev/null"
                todata = ""
            # generate diff
            for line in difflib.unified_diff(fromdata, todata,
                                             fromfile=fromfile, tofile=tofile):
                # coloring diff
                if line.startswith("+"):
                   out("#g#%s#R#" % line, endl="")
                elif line.startswith("-"):
                   out("#r#%s#R#" % line, endl="")
                elif line.startswith("@@"):
                   out("#c#%s#R#" % line, endl="")
                else:
                   out(line, endl="")

    def __init__(self, path, fileobj=None, md5name=False):
        '''
        Initialize a package image
@@ -569,7 +610,6 @@ class PackageImage(Image):
            arrowlevel(level=old_level)
        arrowlevel(-1)


class Payload(object):
    '''
    Payload class represents a payload object
+36 −0
Original line number Diff line number Diff line
@@ -26,6 +26,42 @@ class Repository(object):
    Repository class
    '''

    @classmethod
    def diff(cls, repo1, repo2):
        '''
        Comptue a diff between two repositories
        '''
        arrow("Diff between repositories #y#%s#R# and #g#%s#R#" % (repo1.config.name,
                                                       repo2.config.name))
        # Get info from databases
        i_dict1 = dict((b[0], b[1:]) for b in repo1.db.ask(
                "SELECT md5, name, version FROM image").fetchall())
        i_set1 = set(i_dict1.keys())
        i_dict2 = dict((b[0], b[1:]) for b in repo2.db.ask(
                "SELECT md5, name, version FROM image").fetchall())
        i_set2 = set(i_dict2.keys())
        p_dict1 = dict((b[0], b[1:]) for b in  repo1.db.ask(
                "SELECT md5, name FROM payload").fetchall())
        p_set1 = set(p_dict1.keys())
        p_dict2 = dict((b[0], b[1:]) for b in repo2.db.ask(
                "SELECT md5, name FROM payload").fetchall())
        p_set2 = set(p_dict2.keys())
        # computing diff
        i_only1 = i_set1 - i_set2
        i_only2 = i_set2 - i_set1
        p_only1 = p_set1 - p_set2
        p_only2 = p_set2 - p_set1
        # printing functions
        pimg = lambda r,c,m,d,: out("#%s#Image only in repository %s: %s v%s (%s)#R#" %
                                    (c, r.config.name, d[m][0], d[m][1], m))
        ppay = lambda r,c,m,d,: out("#%s#Payload only in repository %s: %s (%s)#R#" %
                                    (c, r.config.name, d[m][0], m))
        # printing image diff
        for md5 in i_only1: pimg(repo1, "y", md5, i_dict1)
        for md5 in p_only1: ppay(repo1, "y", md5, p_dict1)
        for md5 in i_only2: pimg(repo2, "g", md5, i_dict2)
        for md5 in p_only2: ppay(repo2, "g", md5, p_dict2)

    def __init__(self, config):
        self.config = config
        if not config.offline: