1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#!/usr/bin/python
# Author: Jamie Strandboge <jamie@ubuntu.com>
# Copyright (C) 2012 Canonical Ltd.
#
# This script is distributed under the terms and conditions of the GNU General
# Public License, Version 2 or later. See http://www.gnu.org/copyleft/gpl.html
# for details.
import cPickle
import optparse
import os
import pprint
import signal
import subprocess
import tempfile
import sys
# TODO: use usn_lib.py
def load_database(db_filename):
'''Load usn database'''
print >>sys.stderr, "INFO: Loading %s..." % (db_filename)
filename = os.path.expanduser(db_filename)
if not os.path.isfile(filename):
return {}
return cPickle.load(open(filename))
def get_norm_db_as_str(db):
'''Print the db in a normalized format, that can be used to compare'''
return pprint.pformat(db)
def subprocess_setup():
# Python installs a SIGPIPE handler by default. This is usually not what
# non-Python subprocesses expect.
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
def cmd(command, input = None, stderr = subprocess.STDOUT, stdout = subprocess.PIPE, stdin = None, timeout = None):
'''Try to execute given command (array) and return its stdout, or return
a textual error if it failed.'''
try:
sp = subprocess.Popen(command, stdin=stdin, stdout=stdout, stderr=stderr, close_fds=True, preexec_fn=subprocess_setup)
except OSError, e:
return [127, str(e)]
out, outerr = sp.communicate(input)
# Handle redirection of stdout
if out == None:
out = ''
# Handle redirection of stderr
if outerr == None:
outerr = ''
return [sp.returncode,out+outerr]
def diff_db(db1, db2):
'''Compare two databases'''
tmpdir = tempfile.mkdtemp(prefix='usndb-tool-')
fn1 = os.path.join(tmpdir, "db1")
print >>sys.stderr, "INFO: Formatting %s..." % (os.path.basename(fn1))
open(fn1,'w').write(get_norm_db_as_str(db1))
fn2 = os.path.join(tmpdir, "db2")
print >>sys.stderr, "INFO: Formatting %s..." % (os.path.basename(fn2))
open(fn2,'w').write(get_norm_db_as_str(db2))
print >>sys.stderr, "INFO: diffing %s %s..." % (os.path.basename(fn1), os.path.basename(fn2))
rc, report = cmd(['diff', '-u', fn1, fn2])
os.unlink(fn1)
os.unlink(fn2)
os.rmdir(tmpdir)
return report
#
# main
#
if __name__ == "__main__":
parser = optparse.OptionParser()
parser.add_option("--db", help="database file", metavar="FILE")
parser.add_option("--db2", help="database file", metavar="FILE")
parser.add_option("--diff", help="Perform diff on files", action='store_true', default=False)
parser.add_option("--dump", help="Dump the specified db to stdout", action='store_true', default=False)
(opt, args) = parser.parse_args()
if not opt.db:
print >>sys.stderr, "Must specify --db"
sys.exit(1)
elif not opt.diff and not opt.dump:
print >>sys.stderr, "Must specify one of --diff or --dump"
sys.exit(1)
elif opt.diff and not opt.db2:
print >>sys.stderr, "Must specify --db2"
sys.exit(1)
elif opt.db and not os.path.isfile(opt.db):
print >>sys.stderr, "'%s' is not a file" % opt.db
sys.exit(1)
elif opt.db2 and not os.path.isfile(opt.db2):
print >>sys.stderr, "'%s' is not a file" % opt.db2
sys.exit(1)
db = load_database(opt.db)
if opt.db2:
db2 = load_database(opt.db2)
if opt.diff:
diff = diff_db(db, db2)
if diff != "":
print diff_db(db, db2)
elif opt.dump:
print get_norm_db_as_str(db)
else:
print >>sys.stderr, "Unrecognized command"
sys.exit(1)
sys.exit(0)
|