patch 9.1.0755: quickfix list does not handle hardlinks well

Commit: 
https://github.com/vim/vim/commit/29822996996550f68a781e85753ebd4d177f22da
Author: Austin Chang <austin880...@gmail.com>
Date:   Thu Oct 3 10:50:05 2024 +0200

    patch 9.1.0755: quickfix list does not handle hardlinks well
    
    Problem:  quickfix list does not handle hardlinks well
    Solution: store original file name with quickfix entry
              (Austin Chang)
    
    Quickfix list shows entries with duplicate name if the file is opened
    with the path of hard links.
    
    The major cause is that qflist assumed that the filename passed into
    `qf_add_entry` matches the filename opened with the buffer.
    
    This patch handles this case by introduce a `qf_fname` into `qfline_S`
    structure. It stores the filename from `qf_add_entry` for each quickfix
    line.
    
    closes: #15687
    
    Signed-off-by: Austin Chang <austin880...@gmail.com>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/quickfix.c b/src/quickfix.c
index 6f7d3a58b..79c9fdf39 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -36,6 +36,7 @@ struct qfline_S
     int                qf_end_col;     // column when the error has range or 
zero
     int                qf_nr;          // error number
     char_u     *qf_module;     // module name for this error
+    char_u     *qf_fname;      // different filename if there're hard links
     char_u     *qf_pattern;    // search pattern for the error
     char_u     *qf_text;       // description of the error
     char_u     qf_viscol;      // set to TRUE if qf_col and qf_end_col is
@@ -2173,14 +2174,17 @@ qf_add_entry(
     typval_T   *user_data,     // custom user data or NULL
     int                valid)          // valid entry
 {
+    buf_T      *buf;
     qfline_T   *qfp;
     qfline_T   **lastp;        // pointer to qf_last or NULL
+    char_u     *fullname = NULL;
+    char_u     *p = NULL;
 
     if ((qfp = ALLOC_ONE_ID(qfline_T, aid_qf_qfline)) == NULL)
        return QF_FAIL;
     if (bufnum != 0)
     {
-       buf_T *buf = buflist_findnr(bufnum);
+       buf = buflist_findnr(bufnum);
 
        qfp->qf_fnum = bufnum;
        if (buf != NULL)
@@ -2188,7 +2192,24 @@ qf_add_entry(
                IS_QF_LIST(qfl) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY;
     }
     else
+    {
        qfp->qf_fnum = qf_get_fnum(qfl, dir, fname);
+       buf = buflist_findnr(qfp->qf_fnum);
+    }
+    if (fname != NULL)
+       fullname = fix_fname(fname);
+    qfp->qf_fname = NULL;
+    if (buf != NULL &&
+       buf->b_ffname != NULL && fullname != NULL)
+    {
+        if (fnamecmp(fullname, buf->b_ffname) != 0)
+        {
+            p = shorten_fname1(fullname);
+            if (p != NULL)
+               qfp->qf_fname = vim_strsave(p);
+        }
+    }
+    vim_free(fullname);
     if ((qfp->qf_text = vim_strsave(mesg)) == NULL)
     {
        vim_free(qfp);
@@ -3709,7 +3730,10 @@ qf_list_entry(qfline_T *qfp, int qf_idx, int cursel)
        if (qfp->qf_fnum != 0
                && (buf = buflist_findnr(qfp->qf_fnum)) != NULL)
        {
-           fname = buf->b_fname;
+           if (qfp->qf_fname == NULL)
+               fname = buf->b_fname;
+           else
+               fname = qfp->qf_fname;
            if (qfp->qf_type == 1)      // :helpgrep
                fname = gettail(fname);
        }
@@ -4034,6 +4058,7 @@ qf_free_items(qf_list_T *qfl)
        qfpnext = qfp->qf_next;
        if (!stop)
        {
+           vim_free(qfp->qf_fname);
            vim_free(qfp->qf_module);
            vim_free(qfp->qf_text);
            vim_free(qfp->qf_pattern);
@@ -4761,7 +4786,10 @@ qf_buf_add_line(
                        mch_dirname(dirname, MAXPATHL);
                    shorten_buf_fname(errbuf, dirname, FALSE);
                }
-               ga_concat(gap, errbuf->b_fname);
+               if (qfp->qf_fname == NULL)
+                   ga_concat(gap, errbuf->b_fname);
+               else
+                   ga_concat(gap, qfp->qf_fname);
            }
        }
 
diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim
index 0aa82ef74..93db94075 100644
--- a/src/testdir/test_quickfix.vim
+++ b/src/testdir/test_quickfix.vim
@@ -4277,6 +4277,7 @@ endfunc
 
 " The following test used to crash Vim
 func Test_lvimgrep_crash()
+  " this leaves a swapfile .test_quickfix.vim.swp around, why?
   sv Xtest
   augroup QF_Test
     au!
@@ -4370,6 +4371,8 @@ func Test_vimgrep_autocmd()
   autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f')
   call assert_fails('lvimgrep stars Xtest*.txt', 'E926:')
   au! BufRead Xtest2.txt
+  " cleanup the swap files
+  bw! Xtest2.txt Xtest1.txt
 
   call setqflist([], 'f')
 endfunc
@@ -6578,4 +6581,41 @@ func Test_cbuffer_range()
   call XbufferTests_range('l')
 endfunc
 
+" Test for displaying fname pass from setqflist when the name
+" are hard links to prevent seemly duplicate entries.
+func Xtest_hardlink_fname(cchar)
+  call s:setup_commands(a:cchar)
+  %bwipe
+  " Create a sample source file
+  let lines =<< trim END
+    void sample() {}
+    int main() { sample(); return 0; }
+  END
+  call writefile(lines, 'test_qf_hardlink1.c', 'D')
+  defer delete('test_qf_hardlink1.c')
+  defer delete('test_qf_hardlink2.c')
+  call system('ln test_qf_hardlink1.c test_qf_hardlink2.c')
+  if v:shell_error
+    throw 'Skipped: ln throws error on this platform'
+  endif
+  call g:Xsetlist([], 'f')
+  " Make a qflist that contains the file and it's hard link
+  " like how LSP plugins set response into qflist
+  call g:Xsetlist([{'filename' : 'test_qf_hardlink1.c', 'lnum' : 1},
+        \ {'filename' : 'test_qf_hardlink2.c', 'lnum' : 1}], ' ')
+  Xopen
+  " Ensure that two entries are displayed with different name
+  " so that they aren't seen as duplication.
+  call assert_equal(['test_qf_hardlink1.c|1| ',
+        \ 'test_qf_hardlink2.c|1| '], getline(1, '$'))
+  Xclose
+endfunc
+
+func Test_hardlink_fname()
+  CheckUnix
+  CheckExecutable ln
+  call Xtest_hardlink_fname('c')
+  call Xtest_hardlink_fname('l')
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index 8cc38ccc6..3ea146859 100644
--- a/src/version.c
+++ b/src/version.c
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    755,
 /**/
     754,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/E1swHgs-008XiM-LC%40256bit.org.

Raspunde prin e-mail lui