Implement diffing of directories and allow launching the diff tool via calibre-debug --diff

This commit is contained in:
Kovid Goyal 2014-01-30 11:27:28 +05:30
parent 3c50a45ad6
commit cae211974b
2 changed files with 35 additions and 3 deletions

View File

@ -79,6 +79,9 @@ Everything after the -- is passed to the script.
'Run a plugin that provides a command line interface. For example:\n' 'Run a plugin that provides a command line interface. For example:\n'
'calibre-debug -r "Add Books" -- file1 --option1\n' 'calibre-debug -r "Add Books" -- file1 --option1\n'
'Everything after the -- will be passed to the plugin as arguments.')) 'Everything after the -- will be passed to the plugin as arguments.'))
parser.add_option('--diff', help=_(
'Run the calibre diff tool. For example:\n'
'calibre-debug --diff -- file1 file2'))
return parser return parser
@ -274,6 +277,9 @@ def main(args=sys.argv):
prints(_('No plugin named %s found')%opts.run_plugin) prints(_('No plugin named %s found')%opts.run_plugin)
raise SystemExit(1) raise SystemExit(1)
plugin.cli_main([plugin.name] + args[1:]) plugin.cli_main([plugin.name] + args[1:])
elif opts.diff:
from calibre.gui2.tweak_book.diff.main import main
main(['calibre-diff'] + args[1:])
elif len(args) >= 2 and args[1].rpartition('.')[-1] in {'py', 'recipe'}: elif len(args) >= 2 and args[1].rpartition('.')[-1] in {'py', 'recipe'}:
run_script(args[1], args[2:]) run_script(args[1], args[2:])
elif len(args) >= 2 and args[1].rpartition('.')[-1] in {'mobi', 'azw', 'azw3', 'docx'}: elif len(args) >= 2 and args[1].rpartition('.')[-1] in {'mobi', 'azw', 'azw3', 'docx'}:

View File

@ -6,7 +6,7 @@ from __future__ import (unicode_literals, division, absolute_import,
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>' __copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'
import sys import sys, os
from functools import partial from functools import partial
from PyQt4.Qt import ( from PyQt4.Qt import (
@ -103,7 +103,7 @@ def get_decoded_raw(name):
raw = raw.decode('utf-8') raw = raw.decode('utf-8')
except ValueError: except ValueError:
pass pass
if syntax != 'raster_image': elif syntax != 'raster_image':
if syntax in {'html', 'xml'}: if syntax in {'html', 'xml'}:
raw = xml_to_unicode(raw, verbose=True)[0] raw = xml_to_unicode(raw, verbose=True)[0]
else: else:
@ -123,6 +123,23 @@ def file_diff(left, right):
cache.set_left(left, raw1), cache.set_right(right, raw2) cache.set_left(left, raw1), cache.set_right(right, raw2)
return cache, {left:syntax1, right:syntax2}, {left:right}, {}, set(), set() return cache, {left:syntax1, right:syntax2}, {left:right}, {}, set(), set()
def dir_diff(left, right):
ldata, rdata, lsmap, rsmap = {}, {}, {}, {}
for base, data, smap in ((left, ldata, lsmap), (right, rdata, rsmap)):
for dirpath, dirnames, filenames in os.walk(base):
for filename in filenames:
path = os.path.join(dirpath, filename)
name = os.path.relpath(path, base)
data[name], smap[name] = get_decoded_raw(path)
cache, changed_names, renamed_names, removed_names, added_names = changed_files(
ldata, rdata, ldata.get, rdata.get)
syntax_map = {name:lsmap[name] for name in changed_names}
syntax_map.update({name:lsmap[name] for name in renamed_names})
syntax_map.update({name:rsmap[name] for name in added_names})
syntax_map.update({name:lsmap[name] for name in removed_names})
return cache, syntax_map, changed_names, renamed_names, removed_names, added_names
def container_diff(left, right): def container_diff(left, right):
left_names, right_names = set(left.name_path_map), set(right.name_path_map) left_names, right_names = set(left.name_path_map), set(right.name_path_map)
if left.cloned or right.cloned: if left.cloned or right.cloned:
@ -308,6 +325,13 @@ class Diff(Dialog):
if identical: if identical:
self.reject() self.reject()
def dir_diff(self, left, right, identical_msg=None):
with self:
identical = self.apply_diff(identical_msg or _('The directories are identical'), *dir_diff(left, right))
self.view.finalize()
if identical:
self.reject()
def apply_diff(self, identical_msg, cache, syntax_map, changed_names, renamed_names, removed_names, added_names): def apply_diff(self, identical_msg, cache, syntax_map, changed_names, renamed_names, removed_names, added_names):
self.view.clear() self.view.clear()
self.apply_diff_calls = calls = [] self.apply_diff_calls = calls = []
@ -379,7 +403,9 @@ def compare_books(path1, path2, revert_msg=None, revert_callback=None, parent=No
def main(args=sys.argv): def main(args=sys.argv):
left, right = sys.argv[-2:] left, right = sys.argv[-2:]
ext1, ext2 = left.rpartition('.')[-1].lower(), right.rpartition('.')[-1].lower() ext1, ext2 = left.rpartition('.')[-1].lower(), right.rpartition('.')[-1].lower()
if (ext1, ext2) in {('epub', 'epub'), ('azw3', 'azw3')}: if os.path.isdir(left):
attr = 'dir_diff'
elif (ext1, ext2) in {('epub', 'epub'), ('azw3', 'azw3')}:
attr = 'ebook_diff' attr = 'ebook_diff'
else: else:
attr = 'file_diff' attr = 'file_diff'