{"thread":{"id":"56029","subject":"git difftool: No such file or directory","startedAt":"2021-06-30T09:47:07Z","lastAt":"2021-08-30T00:33:08Z","messageCount":3,"participants":["Alan Blotz","Đoàn Trần Công Danh","David Aguilar"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"428817","messageId":"176caa21-0232-9f21-7a8d-af136754e354@blotz.org","threadId":"56029","inReplyTo":null,"subject":"git difftool: No such file or directory","fromName":"Alan Blotz","fromEmail":"work@blotz.org","sentAt":"2021-06-30T09:38:21Z","receivedAt":"2021-06-30T09:47:07Z","isPatch":false,"sender":{"key":"work@blotz.org","avatar":null},"body":"\n\nThank you for filling out a Git bug report!\nPlease answer the following questions to help us understand your issue.\n\nWhat did you do before the bug happened? (Steps to reproduce your issue)\n\nmkdir broken-diff\ncd broken-diff\ngit init\nmkdir dir1\nmkdir dir2\ntouch dir1/orig\ncd dir2/\nln -s ../dir1/orig sym\ncd ..\ngit add dir*\ngit ci -m \"init\"\ngit checkout -b b\ngit rm dir2/sym \ngit ci -m \"remove\"\ngit difftool -d master HEAD\n\nWhat did you expect to happen? (Expected behavior)\n\ngit difftool shall compare both branches.\n\nWhat happened instead? (Actual behavior)\n\ngit difftool prints an error:\n\nfatal: could not open '/tmp/git-difftool.l4UM7e/left/dir2/sym' for writing: No such file or directory\n\nPlease review the rest of the bug report below.\nYou can delete any lines you don't wish to share.\n\n\n[System Info]\ngit version:\ngit version 2.31.1\ncpu: x86_64\nno commit associated with this build\nsizeof-long: 8\nsizeof-size_t: 8\nshell-path: /bin/sh\nuname: Linux 5.12.12-300.fc34.x86_64 #1 SMP Fri Jun 18 14:30:51 UTC 2021 x86_64\ncompiler info: gnuc: 11.0\nlibc info: glibc: 2.33\n$SHELL (typically, interactive shell): /bin/bash\n\n\n[Enabled Hooks]\n"},{"id":"428864","messageId":"YN0N6tUeSJM1EBHD@danh.dev","threadId":"56029","inReplyTo":"176caa21-0232-9f21-7a8d-af136754e354@blotz.org","subject":"Re: git difftool: No such file or directory","fromName":"Đoàn Trần Công Danh","fromEmail":"congdanhqx@gmail.com","sentAt":"2021-07-01T00:35:54Z","receivedAt":"2021-07-01T00:36:00Z","isPatch":false,"sender":{"key":"congdanhqx@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42673067?v=4"},"body":"On 2021-06-30 11:38:21+0200, Alan Blotz <work@blotz.org> wrote:\n\n> Thank you for filling out a Git bug report!\n> Please answer the following questions to help us understand your issue.\n> \n> What did you do before the bug happened? (Steps to reproduce your issue)\n> \n> mkdir broken-diff\n> cd broken-diff\n> git init\n> mkdir dir1\n> mkdir dir2\n> touch dir1/orig\n> cd dir2/\n> ln -s ../dir1/orig sym\n> cd ..\n> git add dir*\n> git ci -m \"init\"\n> git checkout -b b\n> git rm dir2/sym \n> git ci -m \"remove\"\n> git difftool -d master HEAD\n> \n> What did you expect to happen? (Expected behavior)\n> \n> git difftool shall compare both branches.\n> \n> What happened instead? (Actual behavior)\n> \n> git difftool prints an error:\n> \n> fatal: could not open '/tmp/git-difftool.l4UM7e/left/dir2/sym' for writing: No such file or directory\n\nIt looks like this behaviour was there from the time difftool was\nre-written in C in 03831ef7b5, (difftool: implement the functionality\nin the builtin, 2017-01-19). The perl version didn't have this\nproblem.\n\nThe perl version create a file in place of that symlink and write the\nsymlink's target into that file. The C version tries to write (and\nfollow?) the symlink.\n\nThis hack can fix the problem but I'm not sure it's correct:\n----8<---\n\ndiff --git a/builtin/difftool.c b/builtin/difftool.c\nindex 2115e548a5..737ebb5b1a 100644\n--- a/builtin/difftool.c\n+++ b/builtin/difftool.c\n@@ -492,12 +492,14 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,\n \t\tif (*entry->left) {\n \t\t\tadd_path(&ldir, ldir_len, entry->path);\n \t\t\tensure_leading_directories(ldir.buf);\n-\t\t\twrite_file(ldir.buf, \"%s\", entry->left);\n+\t\t\tunlink(ldir.buf);\n+\t\t\twrite_file_buf(ldir.buf, entry->left, strlen(entry->left));\n \t\t}\n \t\tif (*entry->right) {\n \t\t\tadd_path(&rdir, rdir_len, entry->path);\n \t\t\tensure_leading_directories(rdir.buf);\n-\t\t\twrite_file(rdir.buf, \"%s\", entry->right);\n+\t\t\tunlink(rdir.buf);\n+\t\t\twrite_file_buf(rdir.buf, entry->right, strlen(entry->right));\n \t\t}\n \t}\n---->8----- \n\n+Cc: Dscho, who wrote the C version.\n\n-- \nDanh\n"},{"id":"434041","messageId":"CAJDDKr6Z9E6MbQReTXtF3k9V8YJ-mv9swgsazdD0eeAA35UY0A@mail.gmail.com","threadId":"56029","inReplyTo":"YN0N6tUeSJM1EBHD@danh.dev","subject":"Re: git difftool: No such file or directory","fromName":"David Aguilar","fromEmail":"davvid@gmail.com","sentAt":"2021-08-30T00:32:28Z","receivedAt":"2021-08-30T00:33:08Z","isPatch":false,"sender":{"key":"davvid@gmail.com","avatar":"https://avatars.githubusercontent.com/u/13196?v=4"},"body":"On Wed, Jun 30, 2021 at 5:38 PM Đoàn Trần Công Danh\n<congdanhqx@gmail.com> wrote:\n>\n> On 2021-06-30 11:38:21+0200, Alan Blotz <work@blotz.org> wrote:\n>\n> > Thank you for filling out a Git bug report!\n> > Please answer the following questions to help us understand your issue.\n> >\n> > What did you do before the bug happened? (Steps to reproduce your issue)\n> >\n> > mkdir broken-diff\n> > cd broken-diff\n> > git init\n> > mkdir dir1\n> > mkdir dir2\n> > touch dir1/orig\n> > cd dir2/\n> > ln -s ../dir1/orig sym\n> > cd ..\n> > git add dir*\n> > git ci -m \"init\"\n> > git checkout -b b\n> > git rm dir2/sym\n> > git ci -m \"remove\"\n> > git difftool -d master HEAD\n> >\n> > What did you expect to happen? (Expected behavior)\n> >\n> > git difftool shall compare both branches.\n> >\n> > What happened instead? (Actual behavior)\n> >\n> > git difftool prints an error:\n> >\n> > fatal: could not open '/tmp/git-difftool.l4UM7e/left/dir2/sym' for writing: No such file or directory\n>\n> It looks like this behaviour was there from the time difftool was\n> re-written in C in 03831ef7b5, (difftool: implement the functionality\n> in the builtin, 2017-01-19). The perl version didn't have this\n> problem.\n>\n> The perl version create a file in place of that symlink and write the\n> symlink's target into that file. The C version tries to write (and\n> follow?) the symlink.\n>\n> This hack can fix the problem but I'm not sure it's correct:\n> ----8<---\n>\n> diff --git a/builtin/difftool.c b/builtin/difftool.c\n> index 2115e548a5..737ebb5b1a 100644\n> --- a/builtin/difftool.c\n> +++ b/builtin/difftool.c\n> @@ -492,12 +492,14 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,\n>                 if (*entry->left) {\n>                         add_path(&ldir, ldir_len, entry->path);\n>                         ensure_leading_directories(ldir.buf);\n> -                       write_file(ldir.buf, \"%s\", entry->left);\n> +                       unlink(ldir.buf);\n> +                       write_file_buf(ldir.buf, entry->left, strlen(entry->left));\n>                 }\n>                 if (*entry->right) {\n>                         add_path(&rdir, rdir_len, entry->path);\n>                         ensure_leading_directories(rdir.buf);\n> -                       write_file(rdir.buf, \"%s\", entry->right);\n> +                       unlink(rdir.buf);\n> +                       write_file_buf(rdir.buf, entry->right, strlen(entry->right));\n>                 }\n>         }\n> ---->8-----\n>\n> +Cc: Dscho, who wrote the C version.\n\nThank you for tracking this down!\n\nI re-read the original perl version and this indeed looks like it\nshould do the trick since it's doing the same thing we did in perl.\n\nI'm a little ashamed that we didn't have a test case to cover this use\ncase but the reproduction recipe you included looks like a great\nstart. We already have a few tests that use the SYMLINKS test prereq\nso this would slot in well there.\n-- \nDavid\n"}]}