0
0
mirror of https://github.com/vim/vim.git synced 2025-09-23 03:43:49 -04:00

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 <austin880625@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Austin Chang
2024-10-03 10:50:05 +02:00
committed by Christian Brabandt
parent ae62fe5c28
commit 2982299699
3 changed files with 73 additions and 3 deletions

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -704,6 +704,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
755,
/**/
754,
/**/