Here's a patch to prevent the traceback. It just detects the general situation (comparing a directory with something else) and bails with a more helpful message when they're incompatible.
I checked what diff does, and it does something slightly more nuanced: if you compare directory D against non-directory F, it tries to compare `/D/$(basename F)` against F. If that directory+basename path is itself a directory, then it bails with an error message like the one in this patch. Personally I felt like the path translation wasn't especially helpful, so decided to just bail immediately. -- Brett Smith
>From 7ec9f8df87ec18263a2f327951cffc08a9631fc8 Mon Sep 17 00:00:00 2001 From: Brett Smith <brettcsm...@brettcsmith.org> Date: Mon, 26 Dec 2016 19:26:05 -0500 Subject: [PATCH] comparators: Avoid comparing a directory with non-directory. There's no sensible way to do this comparison, so just bail with an error message. Previously we assumed both paths were files and ran comparator tools on them, which led to more obscure errors. --- diffoscope/comparators/__init__.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/diffoscope/comparators/__init__.py b/diffoscope/comparators/__init__.py index e80b6d5..c97fc3e 100644 --- a/diffoscope/comparators/__init__.py +++ b/diffoscope/comparators/__init__.py @@ -121,11 +121,28 @@ def bail_if_non_existing(*paths): sys.stderr.write('%s: %s: No such file or directory\n' % (sys.argv[0], path)) sys.exit(2) +def bail_if_incompatible_file_types(path1, path1_isdir, path2, path2_isdir): + if path1_isdir == path2_isdir: + return + fmt_args = { + 'prog': sys.argv[0], + 'path1': path1, + 'verb1': "is" if path1_isdir else "is not", + 'path2': path2, + 'verb2': "is" if path2_isdir else "is not", + } + errmsg = "{prog}: {path1} {verb1} a directory while {path2} {verb2}".format(**fmt_args) + print(errmsg, file=sys.stderr) + sys.exit(2) + def compare_root_paths(path1, path2): + path1_isdir = os.path.isdir(path1) + path2_isdir = os.path.isdir(path2) if not Config().new_file: bail_if_non_existing(path1, path2) - if os.path.isdir(path1) and os.path.isdir(path2): + if path1_isdir and path2_isdir: return compare_directories(path1, path2) + bail_if_incompatible_file_types(path1, path1_isdir, path2, path2_isdir) container1 = FilesystemDirectory(os.path.dirname(path1)).as_container file1 = specialize(FilesystemFile(path1, container=container1)) container2 = FilesystemDirectory(os.path.dirname(path2)).as_container -- 2.1.4