Thread (3 messages) 3 messages, 3 authors, 2021-08-30

Re: git difftool: No such file or directory

From: David Aguilar <hidden>
Date: 2021-08-30 00:33:08

On Wed, Jun 30, 2021 at 5:38 PM Đoàn Trần Công Danh
[off-list ref] wrote:
quoted hunk ↗ jump to hunk
On 2021-06-30 11:38:21+0200, Alan Blotz [off-list ref] wrote:
quoted
Thank you for filling out a Git bug report!
Please answer the following questions to help us understand your issue.

What did you do before the bug happened? (Steps to reproduce your issue)

mkdir broken-diff
cd broken-diff
git init
mkdir dir1
mkdir dir2
touch dir1/orig
cd dir2/
ln -s ../dir1/orig sym
cd ..
git add dir*
git ci -m "init"
git checkout -b b
git rm dir2/sym
git ci -m "remove"
git difftool -d master HEAD

What did you expect to happen? (Expected behavior)

git difftool shall compare both branches.

What happened instead? (Actual behavior)

git difftool prints an error:

fatal: could not open '/tmp/git-difftool.l4UM7e/left/dir2/sym' for writing: No such file or directory
It looks like this behaviour was there from the time difftool was
re-written in C in 03831ef7b5, (difftool: implement the functionality
in the builtin, 2017-01-19). The perl version didn't have this
problem.

The perl version create a file in place of that symlink and write the
symlink's target into that file. The C version tries to write (and
follow?) the symlink.

This hack can fix the problem but I'm not sure it's correct:
----8<---
diff --git a/builtin/difftool.c b/builtin/difftool.c
index 2115e548a5..737ebb5b1a 100644
--- a/builtin/difftool.c
+++ b/builtin/difftool.c
@@ -492,12 +492,14 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
                if (*entry->left) {
                        add_path(&ldir, ldir_len, entry->path);
                        ensure_leading_directories(ldir.buf);
-                       write_file(ldir.buf, "%s", entry->left);
+                       unlink(ldir.buf);
+                       write_file_buf(ldir.buf, entry->left, strlen(entry->left));
                }
                if (*entry->right) {
                        add_path(&rdir, rdir_len, entry->path);
                        ensure_leading_directories(rdir.buf);
-                       write_file(rdir.buf, "%s", entry->right);
+                       unlink(rdir.buf);
+                       write_file_buf(rdir.buf, entry->right, strlen(entry->right));
                }
        }
---->8-----

+Cc: Dscho, who wrote the C version.
Thank you for tracking this down!

I re-read the original perl version and this indeed looks like it
should do the trick since it's doing the same thing we did in perl.

I'm a little ashamed that we didn't have a test case to cover this use
case but the reproduction recipe you included looks like a great
start. We already have a few tests that use the SYMLINKS test prereq
so this would slot in well there.
-- 
David
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help