mirror of
https://github.com/neovim/neovim.git
synced 2024-12-25 13:45:15 -07:00
vim-patch:9.1.0755: quickfix list does not handle hardlinks well (#30637)
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: vim/vim#15687
2982299699
Co-authored-by: Austin Chang <austin880625@gmail.com>
This commit is contained in:
parent
7eba016c86
commit
ae0e4071a8
@ -91,6 +91,7 @@ struct qfline_S {
|
|||||||
int qf_end_col; ///< column when the error has range or zero
|
int qf_end_col; ///< column when the error has range or zero
|
||||||
int qf_nr; ///< error number
|
int qf_nr; ///< error number
|
||||||
char *qf_module; ///< module name for this error
|
char *qf_module; ///< module name for this error
|
||||||
|
char *qf_fname; ///< different filename if there're hard links
|
||||||
char *qf_pattern; ///< search pattern for the error
|
char *qf_pattern; ///< search pattern for the error
|
||||||
char *qf_text; ///< description of the error
|
char *qf_text; ///< description of the error
|
||||||
char qf_viscol; ///< set to true if qf_col and qf_end_col is screen column
|
char qf_viscol; ///< set to true if qf_col and qf_end_col is screen column
|
||||||
@ -1866,11 +1867,13 @@ static int qf_add_entry(qf_list_T *qfl, char *dir, char *fname, char *module, in
|
|||||||
char vis_col, char *pattern, int nr, char type, typval_T *user_data,
|
char vis_col, char *pattern, int nr, char type, typval_T *user_data,
|
||||||
char valid)
|
char valid)
|
||||||
{
|
{
|
||||||
|
buf_T *buf;
|
||||||
qfline_T *qfp = xmalloc(sizeof(qfline_T));
|
qfline_T *qfp = xmalloc(sizeof(qfline_T));
|
||||||
|
char *fullname = NULL;
|
||||||
|
char *p = NULL;
|
||||||
|
|
||||||
if (bufnum != 0) {
|
if (bufnum != 0) {
|
||||||
buf_T *buf = buflist_findnr(bufnum);
|
buf = buflist_findnr(bufnum);
|
||||||
|
|
||||||
qfp->qf_fnum = bufnum;
|
qfp->qf_fnum = bufnum;
|
||||||
if (buf != NULL) {
|
if (buf != NULL) {
|
||||||
buf->b_has_qf_entry |=
|
buf->b_has_qf_entry |=
|
||||||
@ -1878,7 +1881,21 @@ static int qf_add_entry(qf_list_T *qfl, char *dir, char *fname, char *module, in
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
qfp->qf_fnum = qf_get_fnum(qfl, dir, fname);
|
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 (path_fnamecmp(fullname, buf->b_ffname) != 0) {
|
||||||
|
p = path_try_shorten_fname(fullname);
|
||||||
|
if (p != NULL) {
|
||||||
|
qfp->qf_fname = xstrdup(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xfree(fullname);
|
||||||
qfp->qf_text = xstrdup(mesg);
|
qfp->qf_text = xstrdup(mesg);
|
||||||
qfp->qf_lnum = lnum;
|
qfp->qf_lnum = lnum;
|
||||||
qfp->qf_end_lnum = end_lnum;
|
qfp->qf_end_lnum = end_lnum;
|
||||||
@ -3145,7 +3162,7 @@ static void qf_list_entry(qfline_T *qfp, int qf_idx, bool cursel)
|
|||||||
buf_T *buf;
|
buf_T *buf;
|
||||||
if (qfp->qf_fnum != 0
|
if (qfp->qf_fnum != 0
|
||||||
&& (buf = buflist_findnr(qfp->qf_fnum)) != NULL) {
|
&& (buf = buflist_findnr(qfp->qf_fnum)) != NULL) {
|
||||||
fname = buf->b_fname;
|
fname = qfp->qf_fname == NULL ? buf->b_fname : qfp->qf_fname;
|
||||||
if (qfp->qf_type == 1) { // :helpgrep
|
if (qfp->qf_type == 1) { // :helpgrep
|
||||||
fname = path_tail(fname);
|
fname = path_tail(fname);
|
||||||
}
|
}
|
||||||
@ -3431,6 +3448,7 @@ static void qf_free_items(qf_list_T *qfl)
|
|||||||
qfline_T *qfp = qfl->qf_start;
|
qfline_T *qfp = qfl->qf_start;
|
||||||
qfline_T *qfpnext = qfp->qf_next;
|
qfline_T *qfpnext = qfp->qf_next;
|
||||||
if (!stop) {
|
if (!stop) {
|
||||||
|
xfree(qfp->qf_fname);
|
||||||
xfree(qfp->qf_module);
|
xfree(qfp->qf_module);
|
||||||
xfree(qfp->qf_text);
|
xfree(qfp->qf_text);
|
||||||
xfree(qfp->qf_pattern);
|
xfree(qfp->qf_pattern);
|
||||||
@ -4059,7 +4077,7 @@ static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, const qfli
|
|||||||
}
|
}
|
||||||
shorten_buf_fname(errbuf, dirname, false);
|
shorten_buf_fname(errbuf, dirname, false);
|
||||||
}
|
}
|
||||||
ga_concat(gap, errbuf->b_fname);
|
ga_concat(gap, qfp->qf_fname == NULL ? errbuf->b_fname : qfp->qf_fname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4140,6 +4140,7 @@ endfunc
|
|||||||
|
|
||||||
" The following test used to crash Vim
|
" The following test used to crash Vim
|
||||||
func Test_lvimgrep_crash()
|
func Test_lvimgrep_crash()
|
||||||
|
" this leaves a swapfile .test_quickfix.vim.swp around, why?
|
||||||
sv Xtest
|
sv Xtest
|
||||||
augroup QF_Test
|
augroup QF_Test
|
||||||
au!
|
au!
|
||||||
@ -4202,8 +4203,8 @@ endfunc
|
|||||||
" :vimgrep/:lvimgrep commands are running.
|
" :vimgrep/:lvimgrep commands are running.
|
||||||
func Test_vimgrep_autocmd()
|
func Test_vimgrep_autocmd()
|
||||||
call setqflist([], 'f')
|
call setqflist([], 'f')
|
||||||
call writefile(['stars'], 'Xtest1.txt')
|
call writefile(['stars'], 'Xtest1.txt', 'D')
|
||||||
call writefile(['stars'], 'Xtest2.txt')
|
call writefile(['stars'], 'Xtest2.txt', 'D')
|
||||||
|
|
||||||
" Test 1:
|
" Test 1:
|
||||||
" When searching for a pattern using :vimgrep, if the quickfix list is
|
" When searching for a pattern using :vimgrep, if the quickfix list is
|
||||||
@ -4233,9 +4234,9 @@ func Test_vimgrep_autocmd()
|
|||||||
autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f')
|
autocmd BufRead Xtest2.txt call setloclist(g:save_winid, [], 'f')
|
||||||
call assert_fails('lvimgrep stars Xtest*.txt', 'E926:')
|
call assert_fails('lvimgrep stars Xtest*.txt', 'E926:')
|
||||||
au! BufRead Xtest2.txt
|
au! BufRead Xtest2.txt
|
||||||
|
" cleanup the swap files
|
||||||
|
bw! Xtest2.txt Xtest1.txt
|
||||||
|
|
||||||
call delete('Xtest1.txt')
|
|
||||||
call delete('Xtest2.txt')
|
|
||||||
call setqflist([], 'f')
|
call setqflist([], 'f')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
@ -6458,4 +6459,41 @@ func Test_cbuffer_range()
|
|||||||
call XbufferTests_range('l')
|
call XbufferTests_range('l')
|
||||||
endfunc
|
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
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
Loading…
Reference in New Issue
Block a user