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

Reply via email to