Skip to content
Snippets Groups Projects
Commit a1eb7c45 authored by Seblu's avatar Seblu
Browse files

Add diff command

parent 7de5cb42
No related branches found
No related tags found
No related merge requests found
......@@ -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,
......
......@@ -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
......
......@@ -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:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment