Skip to content

Commit

Permalink
patch 9.0.1007: there is no way to get a list of swap file names
Browse files Browse the repository at this point in the history
Problem:    There is no way to get a list of swap file names.
Solution:   Add the swapfilelist() function.  Use it in the test script to
            clean up.  Remove deleting individual swap files.
  • Loading branch information
brammool committed Dec 5, 2022
1 parent 6521405 commit c216a7a
Show file tree
Hide file tree
Showing 14 changed files with 104 additions and 71 deletions.
12 changes: 12 additions & 0 deletions runtime/doc/builtin.txt
Expand Up @@ -608,6 +608,7 @@ submatch({nr} [, {list}]) String or List
specific match in ":s" or substitute()
substitute({expr}, {pat}, {sub}, {flags})
String all {pat} in {expr} replaced with {sub}
swapfilelist() List swap files found in 'directory'
swapinfo({fname}) Dict information about swap file {fname}
swapname({buf}) String swap file of buffer {buf}
synID({lnum}, {col}, {trans}) Number syntax ID at {lnum} and {col}
Expand Down Expand Up @@ -9314,6 +9315,17 @@ substitute({string}, {pat}, {sub}, {flags}) *substitute()*
Can also be used as a |method|: >
GetString()->substitute(pat, sub, flags)
swapfilelist() *swapfilelist()*
Returns a list of swap file names, like what "vim -r" shows.
See the |-r| command argument. The 'directory' option is used
for the directories to inspect. If you only want to get a
list of swap files in the current directory then temporarily
set 'directory' to a dot: >
let save_dir = &directory
let &directory = '.'
let swapfiles = swapfilelist()
let &directory = save_dir
swapinfo({fname}) *swapinfo()*
The result is a dictionary, which holds information about the
swapfile {fname}. The available fields are:
Expand Down
1 change: 1 addition & 0 deletions runtime/doc/usr_41.txt
Expand Up @@ -1031,6 +1031,7 @@ Buffers, windows and the argument list:
getwininfo() get a list with window information
getchangelist() get a list of change list entries
getjumplist() get a list of jump list entries
swapfilelist() list of existing swap files in 'directory'
swapinfo() information about a swap file
swapname() get the swap file path of a buffer

Expand Down
14 changes: 14 additions & 0 deletions src/evalfunc.c
Expand Up @@ -168,6 +168,7 @@ static void f_split(typval_T *argvars, typval_T *rettv);
static void f_srand(typval_T *argvars, typval_T *rettv);
static void f_submatch(typval_T *argvars, typval_T *rettv);
static void f_substitute(typval_T *argvars, typval_T *rettv);
static void f_swapfilelist(typval_T *argvars, typval_T *rettv);
static void f_swapinfo(typval_T *argvars, typval_T *rettv);
static void f_swapname(typval_T *argvars, typval_T *rettv);
static void f_synID(typval_T *argvars, typval_T *rettv);
Expand Down Expand Up @@ -2579,6 +2580,8 @@ static funcentry_T global_functions[] =
ret_string, f_submatch},
{"substitute", 4, 4, FEARG_1, arg4_string_string_any_string,
ret_string, f_substitute},
{"swapfilelist", 0, 0, 0, NULL,
ret_list_string, f_swapfilelist},
{"swapinfo", 1, 1, FEARG_1, arg1_string,
ret_dict_any, f_swapinfo},
{"swapname", 1, 1, FEARG_1, arg1_buffer,
Expand Down Expand Up @@ -10170,6 +10173,17 @@ f_substitute(typval_T *argvars, typval_T *rettv)
rettv->vval.v_string = do_string_sub(str, pat, sub, expr, flg);
}

/*
* "swapfilelist()" function
*/
static void
f_swapfilelist(typval_T *argvars UNUSED, typval_T *rettv)
{
if (rettv_list_alloc(rettv) == FAIL)
return;
recover_names(NULL, FALSE, rettv->vval.v_list, 0, NULL);
}

/*
* "swapinfo(swap_filename)" function
*/
Expand Down
2 changes: 1 addition & 1 deletion src/main.c
Expand Up @@ -507,7 +507,7 @@ vim_main2(void)
*/
if (recoverymode && params.fname == NULL)
{
recover_names(NULL, TRUE, 0, NULL);
recover_names(NULL, TRUE, NULL, 0, NULL);
mch_exit(0);
}

Expand Down
43 changes: 30 additions & 13 deletions src/memline.c
Expand Up @@ -1208,7 +1208,7 @@ ml_recover(int checkext)
directly = FALSE;

// count the number of matching swap files
len = recover_names(fname, FALSE, 0, NULL);
len = recover_names(fname, FALSE, NULL, 0, NULL);
if (len == 0) // no swap files found
{
semsg(_(e_no_swap_file_found_for_str), fname);
Expand All @@ -1219,15 +1219,15 @@ ml_recover(int checkext)
else // several swap files found, choose
{
// list the names of the swap files
(void)recover_names(fname, TRUE, 0, NULL);
(void)recover_names(fname, TRUE, NULL, 0, NULL);
msg_putchar('\n');
msg_puts(_("Enter number of swap file to use (0 to quit): "));
i = get_number(FALSE, NULL);
if (i < 1 || i > len)
goto theend;
}
// get the swap file name that will be used
(void)recover_names(fname, FALSE, i, &fname_used);
(void)recover_names(fname, FALSE, NULL, i, &fname_used);
}
if (fname_used == NULL)
goto theend; // out of memory
Expand Down Expand Up @@ -1801,12 +1801,14 @@ ml_recover(int checkext)
* - list the swap files for "vim -r"
* - count the number of swap files when recovering
* - list the swap files when recovering
* - list the swap files for swapfilelist()
* - find the name of the n'th swap file when recovering
*/
int
recover_names(
char_u *fname, // base for swap file name
int list, // when TRUE, list the swap file names
int do_list, // when TRUE, list the swap file names
list_T *ret_list UNUSED, // when not NULL add file names to it
int nr, // when non-zero, return nr'th swap file name
char_u **fname_out) // result when "nr" > 0
{
Expand All @@ -1817,7 +1819,6 @@ recover_names(
int num_files;
int file_count = 0;
char_u **files;
int i;
char_u *dirp;
char_u *dir_name;
char_u *fname_res = NULL;
Expand All @@ -1837,7 +1838,7 @@ recover_names(
fname_res = fname;
}

if (list)
if (do_list)
{
// use msg() to start the scrolling properly
msg(_("Swap files found:"));
Expand Down Expand Up @@ -1938,7 +1939,7 @@ recover_names(
}

// check for out-of-memory
for (i = 0; i < num_names; ++i)
for (int i = 0; i < num_names; ++i)
{
if (names[i] == NULL)
{
Expand Down Expand Up @@ -1987,12 +1988,14 @@ recover_names(
}

/*
* remove swapfile name of the current buffer, it must be ignored
* Remove swapfile name of the current buffer, it must be ignored.
* But keep it for swapfilelist().
*/
if (curbuf->b_ml.ml_mfp != NULL
&& (p = curbuf->b_ml.ml_mfp->mf_fname) != NULL)
&& (p = curbuf->b_ml.ml_mfp->mf_fname) != NULL
&& ret_list == NULL)
{
for (i = 0; i < num_files; ++i)
for (int i = 0; i < num_files; ++i)
// Do not expand wildcards, on windows would try to expand
// "%tmp%" in "%tmp%file".
if (fullpathcmp(p, files[i], TRUE, FALSE) & FPC_SAME)
Expand All @@ -2018,7 +2021,7 @@ recover_names(
dirp = (char_u *)""; // stop searching
}
}
else if (list)
else if (do_list)
{
if (dir_name[0] == '.' && dir_name[1] == NUL)
{
Expand All @@ -2036,7 +2039,7 @@ recover_names(

if (num_files)
{
for (i = 0; i < num_files; ++i)
for (int i = 0; i < num_files; ++i)
{
// print the swap file name
msg_outnum((long)++file_count);
Expand All @@ -2050,10 +2053,24 @@ recover_names(
msg_puts(_(" -- none --\n"));
out_flush();
}
#ifdef FEAT_EVAL
else if (ret_list != NULL)
{
for (int i = 0; i < num_files; ++i)
{
char_u *name = concat_fnames(dir_name, files[i], TRUE);
if (name != NULL)
{
list_append_string(ret_list, name, -1);
vim_free(name);
}
}
}
#endif
else
file_count += num_files;

for (i = 0; i < num_names; ++i)
for (int i = 0; i < num_names; ++i)
vim_free(names[i]);
if (num_files > 0)
FreeWild(num_files, files);
Expand Down
2 changes: 1 addition & 1 deletion src/proto/memline.pro
Expand Up @@ -10,7 +10,7 @@ void ml_close_all(int del_file);
void ml_close_notmod(void);
void ml_timestamp(buf_T *buf);
void ml_recover(int checkext);
int recover_names(char_u *fname, int list, int nr, char_u **fname_out);
int recover_names(char_u *fname, int do_list, list_T *ret_list, int nr, char_u **fname_out);
char_u *make_percent_swname(char_u *dir, char_u *name);
void get_b0_dict(char_u *fname, dict_T *d);
void ml_sync_all(int check_file, int check_char);
Expand Down
34 changes: 34 additions & 0 deletions src/testdir/runtest.vim
Expand Up @@ -160,6 +160,14 @@ if has('mac')
let $BASH_SILENCE_DEPRECATION_WARNING = 1
endif


" A previous (failed) test run may have left swap files behind. Delete them
" before running tests again, they might interfere.
for name in s:GetSwapFileList()
call delete(name)
endfor


" Prepare for calling test_garbagecollect_now().
let v:testing = 1

Expand All @@ -186,6 +194,22 @@ if has('reltime')
let g:func_start = reltime()
endif

" Get the list of swap files in the current directory.
func s:GetSwapFileList()
let save_dir = &directory
let &directory = '.'
let files = swapfilelist()
let &directory = save_dir

" remove a match with runtest.vim
let idx = indexof(files, 'v:val =~ "runtest.vim."')
if idx >= 0
call remove(files, idx)
endif

return files
endfunc

" Invoked when a test takes too much time.
func TestTimeout(id)
split test.log
Expand Down Expand Up @@ -339,6 +363,16 @@ func RunTheTest(test)
endif
call add(s:messages, message)
let s:done += 1

" Check if the test has left any swap files behind. Delete them before
" running tests again, they might interfere.
let swapfiles = s:GetSwapFileList()
if len(swapfiles) > 0
call add(s:messages, "Found swap files: " .. string(swapfiles))
for name in swapfiles
call delete(name)
endfor
endif
endfunc

func AfterTheTest(func_name)
Expand Down
8 changes: 0 additions & 8 deletions src/testdir/test_suspend.vim
Expand Up @@ -28,9 +28,6 @@ func Test_suspend()
sleep 150m
endif

" in case a previous failure left a swap file behind
call delete('.Xfoo.swp')

let buf = term_start('/bin/sh')
" Wait for shell prompt.
call WaitForAssert({-> assert_match('[$#] $', term_getline(buf, '.'))})
Expand Down Expand Up @@ -69,7 +66,6 @@ func Test_suspend()

exe buf . 'bwipe!'
call delete('Xfoo')
call delete('.Xfoo.swp')
endfunc

func Test_suspend_autocmd()
Expand All @@ -82,9 +78,6 @@ func Test_suspend_autocmd()
sleep 150m
endif

" in case a previous failure left a swap file behind
call delete('.Xfoo.swp')

let buf = term_start('/bin/sh', #{term_rows: 6})
" Wait for shell prompt.
call WaitForAssert({-> assert_match('[$#] $', term_getline(buf, '.'))})
Expand Down Expand Up @@ -123,7 +116,6 @@ func Test_suspend_autocmd()

exe buf . 'bwipe!'
call delete('Xfoo')
call delete('.Xfoo.swp')
endfunc

" vim: shiftwidth=2 sts=2 expandtab
9 changes: 9 additions & 0 deletions src/testdir/test_swap.vim
Expand Up @@ -110,6 +110,15 @@ func Test_swapinfo()
w
let fname = s:swapname()
call assert_match('Xswapinfo', fname)

let nr = 0
for name in swapfilelist()
if name =~ '[\\/]' .. fname .. '$'
let nr += 1
endif
endfor
call assert_equal(1, nr)

let info = fname->swapinfo()

let ver = printf('VIM %d.%d', v:version / 100, v:version % 100)
Expand Down

0 comments on commit c216a7a

Please sign in to comment.