Patch 8.1.1231
Problem: Asking about existing swap file unnecessarily.
Solution: When it is safe, delete the swap file. Remove
HAS_SWAP_EXISTS_ACTION, it is always defined. (closes #1237)
Files: src/memline.c, src/globals.h, src/buffer.c, src/ex_cmds.c,
src/fileio.c, src/main.c, src/testdir/test_swap.vim,
runtime/doc/usr_11.txt, src/os_win32.c, src/proto/os_win32.pro,
src/os_unix.c, src/proto/os_unix.pro
*** ../vim-8.1.1230/src/memline.c 2019-04-28 19:46:17.030060105 +0200
--- src/memline.c 2019-04-28 22:22:42.217091959 +0200
***************
*** 2159,2167 ****
{
msg_puts(_("\n process ID: "));
msg_outnum(char_to_long(b0.b0_pid));
! #if defined(UNIX)
! /* EMX kill() not working correctly, it seems */
! if (kill((pid_t)char_to_long(b0.b0_pid), 0) == 0)
{
msg_puts(_(" (STILL RUNNING)"));
# if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
--- 2159,2166 ----
{
msg_puts(_("\n process ID: "));
msg_outnum(char_to_long(b0.b0_pid));
! #if defined(UNIX) || defined(MSWIN)
! if (mch_process_running((pid_t)char_to_long(b0.b0_pid)))
{
msg_puts(_(" (STILL RUNNING)"));
# if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
***************
*** 2193,2198 ****
--- 2192,2248 ----
return x;
}
+ /*
+ * Return TRUE if the swap file looks OK and there are no changes, thus it can
+ * be safely deleted.
+ */
+ static time_t
+ swapfile_unchanged(char_u *fname)
+ {
+ stat_T st;
+ int fd;
+ struct block0 b0;
+ int ret = TRUE;
+ #ifdef UNIX
+ long pid;
+ #endif
+
+ // must be able to stat the swap file
+ if (mch_stat((char *)fname, &st) == -1)
+ return FALSE;
+
+ // must be able to read the first block
+ fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
+ if (fd < 0)
+ return FALSE;
+ if (read_eintr(fd, &b0, sizeof(b0)) != sizeof(b0))
+ {
+ close(fd);
+ return FALSE;
+ }
+
+ // the ID and magic number must be correct
+ if (ml_check_b0_id(&b0) == FAIL|| b0_magic_wrong(&b0))
+ ret = FALSE;
+
+ // must be unchanged
+ if (b0.b0_dirty)
+ ret = FALSE;
+
+ #if defined(UNIX) || defined(MSWIN)
+ // process must known and not be running
+ pid = char_to_long(b0.b0_pid);
+ if (pid == 0L || mch_process_running((pid_t)pid))
+ ret = FALSE;
+ #endif
+
+ // TODO: Should we check if the swap file was created on the current
+ // system? And the current user?
+
+ close(fd);
+ return ret;
+ }
+
static int
recov_file_names(char_u **names, char_u *path, int prepend_dot)
{
***************
*** 4757,4765 ****
if (differ == FALSE && !(curbuf->b_flags & BF_RECOVERED)
&& vim_strchr(p_shm, SHM_ATTENTION) == NULL)
{
- #if defined(HAS_SWAP_EXISTS_ACTION)
int choice = 0;
! #endif
#ifdef CREATE_DUMMY_FILE
int did_use_dummy = FALSE;
--- 4807,4814 ----
if (differ == FALSE && !(curbuf->b_flags & BF_RECOVERED)
&& vim_strchr(p_shm, SHM_ATTENTION) == NULL)
{
int choice = 0;
! stat_T st;
#ifdef CREATE_DUMMY_FILE
int did_use_dummy = FALSE;
***************
*** 4779,4791 ****
#if (defined(UNIX) || defined(VMS)) && (defined(FEAT_GUI_DIALOG) ||
defined(FEAT_CON_DIALOG))
process_still_running = FALSE;
#endif
#if defined(FEAT_EVAL)
/*
* If there is an SwapExists autocommand and we can handle
* the response, trigger it. It may return 0 to ask the
* user anyway.
*/
! if (swap_exists_action != SEA_NONE
&& has_autocmd(EVENT_SWAPEXISTS, buf_fname, buf))
choice = do_swapexists(buf, fname);
--- 4828,4852 ----
#if (defined(UNIX) || defined(VMS)) && (defined(FEAT_GUI_DIALOG) ||
defined(FEAT_CON_DIALOG))
process_still_running = FALSE;
#endif
+ // It's safe to delete the swap file if all these are true:
+ // - the edited file exists
+ // - the swap file has no changes and looks OK
+ if (mch_stat((char *)buf->b_fname, &st) == 0
+ && swapfile_unchanged(fname))
+ {
+ choice = 4;
+ if (p_verbose > 0)
+ verb_msg(_("Found a swap file that is not useful,
deleting it"));
+ }
+
#if defined(FEAT_EVAL)
/*
* If there is an SwapExists autocommand and we can handle
* the response, trigger it. It may return 0 to ask the
* user anyway.
*/
! if (choice == 0
! && swap_exists_action != SEA_NONE
&& has_autocmd(EVENT_SWAPEXISTS, buf_fname, buf))
choice = do_swapexists(buf, fname);
***************
*** 4850,4856 ****
}
#endif
- #if defined(HAS_SWAP_EXISTS_ACTION)
if (choice > 0)
{
switch (choice)
--- 4911,4916 ----
***************
*** 4880,4886 ****
break;
}
else
- #endif
{
msg_puts("\n");
if (msg_silent == 0)
--- 4940,4945 ----
*** ../vim-8.1.1230/src/globals.h 2019-04-28 19:46:17.026060122 +0200
--- src/globals.h 2019-04-28 22:14:01.975212661 +0200
***************
*** 966,972 ****
EXTERN int emsg_noredir INIT(= 0); /* don't redirect error messages */
EXTERN int cmd_silent INIT(= FALSE); /* don't echo the command line */
- # define HAS_SWAP_EXISTS_ACTION
EXTERN int swap_exists_action INIT(= SEA_NONE);
/* For dialog when swap file already
* exists. */
--- 966,971 ----
***************
*** 1644,1649 ****
--- 1643,1651 ----
#endif
#ifdef MSWIN
+ # ifdef PROTO
+ typedef int HINSTANCE;
+ # endif
EXTERN int ctrl_break_was_pressed INIT(= FALSE);
EXTERN HINSTANCE g_hinst INIT(= NULL);
#endif
*** ../vim-8.1.1230/src/buffer.c 2019-04-28 18:04:56.054492198 +0200
--- src/buffer.c 2019-04-28 20:19:17.859717974 +0200
***************
*** 972,1014 ****
int dir,
int count)
{
- #if defined(HAS_SWAP_EXISTS_ACTION)
bufref_T old_curbuf;
set_bufref(&old_curbuf, curbuf);
swap_exists_action = SEA_DIALOG;
- #endif
(void)do_buffer(*eap->cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
start, dir, count, eap->forceit);
- #if defined(HAS_SWAP_EXISTS_ACTION)
if (swap_exists_action == SEA_QUIT && *eap->cmd == 's')
{
! # if defined(FEAT_EVAL)
cleanup_T cs;
/* Reset the error/interrupt/exception state here so that
* aborting() returns FALSE when closing a window. */
enter_cleanup(&cs);
! # endif
/* Quitting means closing the split window, nothing else. */
win_close(curwin, TRUE);
swap_exists_action = SEA_NONE;
swap_exists_did_quit = TRUE;
! # if defined(FEAT_EVAL)
/* Restore the error/interrupt/exception state if not discarded by a
* new aborting error, interrupt, or uncaught exception. */
leave_cleanup(&cs);
! # endif
}
else
handle_swap_exists(&old_curbuf);
- #endif
}
- #if defined(HAS_SWAP_EXISTS_ACTION) || defined(PROTO)
/*
* Handle the situation of swap_exists_action being set.
* It is allowed for "old_curbuf" to be NULL or invalid.
--- 972,1009 ----
int dir,
int count)
{
bufref_T old_curbuf;
set_bufref(&old_curbuf, curbuf);
swap_exists_action = SEA_DIALOG;
(void)do_buffer(*eap->cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
start, dir, count, eap->forceit);
if (swap_exists_action == SEA_QUIT && *eap->cmd == 's')
{
! #if defined(FEAT_EVAL)
cleanup_T cs;
/* Reset the error/interrupt/exception state here so that
* aborting() returns FALSE when closing a window. */
enter_cleanup(&cs);
! #endif
/* Quitting means closing the split window, nothing else. */
win_close(curwin, TRUE);
swap_exists_action = SEA_NONE;
swap_exists_did_quit = TRUE;
! #if defined(FEAT_EVAL)
/* Restore the error/interrupt/exception state if not discarded by a
* new aborting error, interrupt, or uncaught exception. */
leave_cleanup(&cs);
! #endif
}
else
handle_swap_exists(&old_curbuf);
}
/*
* Handle the situation of swap_exists_action being set.
* It is allowed for "old_curbuf" to be NULL or invalid.
***************
*** 1016,1036 ****
void
handle_swap_exists(bufref_T *old_curbuf)
{
! # if defined(FEAT_EVAL)
cleanup_T cs;
! # endif
! # ifdef FEAT_SYN_HL
long old_tw = curbuf->b_p_tw;
! # endif
buf_T *buf;
if (swap_exists_action == SEA_QUIT)
{
! # if defined(FEAT_EVAL)
/* Reset the error/interrupt/exception state here so that
* aborting() returns FALSE when closing a buffer. */
enter_cleanup(&cs);
! # endif
/* User selected Quit at ATTENTION prompt. Go back to previous
* buffer. If that buffer is gone or the same as the current one,
--- 1011,1031 ----
void
handle_swap_exists(bufref_T *old_curbuf)
{
! #if defined(FEAT_EVAL)
cleanup_T cs;
! #endif
! #ifdef FEAT_SYN_HL
long old_tw = curbuf->b_p_tw;
! #endif
buf_T *buf;
if (swap_exists_action == SEA_QUIT)
{
! #if defined(FEAT_EVAL)
/* Reset the error/interrupt/exception state here so that
* aborting() returns FALSE when closing a buffer. */
enter_cleanup(&cs);
! #endif
/* User selected Quit at ATTENTION prompt. Go back to previous
* buffer. If that buffer is gone or the same as the current one,
***************
*** 1053,1078 ****
// restore msg_silent, so that the command line will be shown
msg_silent = old_msg_silent;
! # ifdef FEAT_SYN_HL
if (old_tw != curbuf->b_p_tw)
check_colorcolumn(curwin);
! # endif
}
/* If "old_curbuf" is NULL we are in big trouble here... */
! # if defined(FEAT_EVAL)
/* Restore the error/interrupt/exception state if not discarded by a
* new aborting error, interrupt, or uncaught exception. */
leave_cleanup(&cs);
! # endif
}
else if (swap_exists_action == SEA_RECOVER)
{
! # if defined(FEAT_EVAL)
/* Reset the error/interrupt/exception state here so that
* aborting() returns FALSE when closing a buffer. */
enter_cleanup(&cs);
! # endif
/* User selected Recover at ATTENTION prompt. */
msg_scroll = TRUE;
--- 1048,1073 ----
// restore msg_silent, so that the command line will be shown
msg_silent = old_msg_silent;
! #ifdef FEAT_SYN_HL
if (old_tw != curbuf->b_p_tw)
check_colorcolumn(curwin);
! #endif
}
/* If "old_curbuf" is NULL we are in big trouble here... */
! #if defined(FEAT_EVAL)
/* Restore the error/interrupt/exception state if not discarded by a
* new aborting error, interrupt, or uncaught exception. */
leave_cleanup(&cs);
! #endif
}
else if (swap_exists_action == SEA_RECOVER)
{
! #if defined(FEAT_EVAL)
/* Reset the error/interrupt/exception state here so that
* aborting() returns FALSE when closing a buffer. */
enter_cleanup(&cs);
! #endif
/* User selected Recover at ATTENTION prompt. */
msg_scroll = TRUE;
***************
*** 1081,1095 ****
cmdline_row = msg_row;
do_modelines(0);
! # if defined(FEAT_EVAL)
/* Restore the error/interrupt/exception state if not discarded by a
* new aborting error, interrupt, or uncaught exception. */
leave_cleanup(&cs);
! # endif
}
swap_exists_action = SEA_NONE;
}
- #endif
/*
* do_bufdel() - delete or unload buffer(s)
--- 1076,1089 ----
cmdline_row = msg_row;
do_modelines(0);
! #if defined(FEAT_EVAL)
/* Restore the error/interrupt/exception state if not discarded by a
* new aborting error, interrupt, or uncaught exception. */
leave_cleanup(&cs);
! #endif
}
swap_exists_action = SEA_NONE;
}
/*
* do_bufdel() - delete or unload buffer(s)
***************
*** 5259,5286 ****
continue;
/* Open the buffer in this window. */
- #if defined(HAS_SWAP_EXISTS_ACTION)
swap_exists_action = SEA_DIALOG;
- #endif
set_curbuf(buf, DOBUF_GOTO);
if (!bufref_valid(&bufref))
{
/* autocommands deleted the buffer!!! */
- #if defined(HAS_SWAP_EXISTS_ACTION)
swap_exists_action = SEA_NONE;
- #endif
break;
}
- #if defined(HAS_SWAP_EXISTS_ACTION)
if (swap_exists_action == SEA_QUIT)
{
! # if defined(FEAT_EVAL)
cleanup_T cs;
/* Reset the error/interrupt/exception state here so that
* aborting() returns FALSE when closing a window. */
enter_cleanup(&cs);
! # endif
/* User selected Quit at ATTENTION prompt; close this window. */
win_close(curwin, TRUE);
--- 5253,5275 ----
continue;
/* Open the buffer in this window. */
swap_exists_action = SEA_DIALOG;
set_curbuf(buf, DOBUF_GOTO);
if (!bufref_valid(&bufref))
{
/* autocommands deleted the buffer!!! */
swap_exists_action = SEA_NONE;
break;
}
if (swap_exists_action == SEA_QUIT)
{
! #if defined(FEAT_EVAL)
cleanup_T cs;
/* Reset the error/interrupt/exception state here so that
* aborting() returns FALSE when closing a window. */
enter_cleanup(&cs);
! #endif
/* User selected Quit at ATTENTION prompt; close this window. */
win_close(curwin, TRUE);
***************
*** 5288,5303 ****
swap_exists_action = SEA_NONE;
swap_exists_did_quit = TRUE;
! # if defined(FEAT_EVAL)
/* Restore the error/interrupt/exception state if not
* discarded by a new aborting error, interrupt, or uncaught
* exception. */
leave_cleanup(&cs);
! # endif
}
else
handle_swap_exists(NULL);
- #endif
}
ui_breakcheck();
--- 5277,5291 ----
swap_exists_action = SEA_NONE;
swap_exists_did_quit = TRUE;
! #if defined(FEAT_EVAL)
/* Restore the error/interrupt/exception state if not
* discarded by a new aborting error, interrupt, or uncaught
* exception. */
leave_cleanup(&cs);
! #endif
}
else
handle_swap_exists(NULL);
}
ui_breakcheck();
*** ../vim-8.1.1230/src/ex_cmds.c 2019-04-28 19:46:17.022060143 +0200
--- src/ex_cmds.c 2019-04-28 20:19:31.859649114 +0200
***************
*** 4258,4266 ****
topline = curwin->w_topline;
if (!oldbuf) /* need to read the file */
{
- #if defined(HAS_SWAP_EXISTS_ACTION)
swap_exists_action = SEA_DIALOG;
- #endif
curbuf->b_flags |= BF_CHECK_RO; /* set/reset 'ro' flag */
/*
--- 4258,4264 ----
***************
*** 4273,4283 ****
(void)open_buffer(FALSE, eap, readfile_flags);
#endif
- #if defined(HAS_SWAP_EXISTS_ACTION)
if (swap_exists_action == SEA_QUIT)
retval = FAIL;
handle_swap_exists(&old_curbuf);
- #endif
}
else
{
--- 4271,4279 ----
*** ../vim-8.1.1230/src/fileio.c 2019-04-28 19:46:17.026060122 +0200
--- src/fileio.c 2019-04-28 20:19:41.807600177 +0200
***************
*** 684,698 ****
#endif
}
! #if defined(HAS_SWAP_EXISTS_ACTION)
! /* If "Quit" selected at ATTENTION dialog, don't load the file */
if (swap_exists_action == SEA_QUIT)
{
if (!read_buffer && !read_stdin)
close(fd);
return FAIL;
}
- #endif
++no_wait_return; /* don't wait for return yet */
--- 684,696 ----
#endif
}
! // If "Quit" selected at ATTENTION dialog, don't load the file
if (swap_exists_action == SEA_QUIT)
{
if (!read_buffer && !read_stdin)
close(fd);
return FAIL;
}
++no_wait_return; /* don't wait for return yet */
*** ../vim-8.1.1230/src/main.c 2019-04-28 19:46:17.030060105 +0200
--- src/main.c 2019-04-28 20:21:01.743207196 +0200
***************
*** 50,58 ****
static void exe_commands(mparm_T *parmp);
static void source_startup_scripts(mparm_T *parmp);
static void main_start_gui(void);
- # if defined(HAS_SWAP_EXISTS_ACTION)
static void check_swap_exists_action(void);
- # endif
# ifdef FEAT_EVAL
static void set_progpath(char_u *argv0);
# endif
--- 50,56 ----
***************
*** 784,802 ****
*/
if (params.tagname != NULL)
{
- #if defined(HAS_SWAP_EXISTS_ACTION)
swap_exists_did_quit = FALSE;
- #endif
vim_snprintf((char *)IObuff, IOSIZE, "ta %s", params.tagname);
do_cmdline_cmd(IObuff);
TIME_MSG("jumping to tag");
- #if defined(HAS_SWAP_EXISTS_ACTION)
/* If the user doesn't want to edit the file then we quit here. */
if (swap_exists_did_quit)
getout(1);
- #endif
}
/* Execute any "+", "-c" and "-S" arguments. */
--- 782,796 ----
***************
*** 2625,2644 ****
{
int i;
! #if defined(HAS_SWAP_EXISTS_ACTION)
! /* When getting the ATTENTION prompt here, use a dialog */
swap_exists_action = SEA_DIALOG;
! #endif
no_wait_return = TRUE;
i = msg_didany;
set_buflisted(TRUE);
! (void)open_buffer(TRUE, NULL, 0); /* create memfile and read file */
no_wait_return = FALSE;
msg_didany = i;
TIME_MSG("reading stdin");
! #if defined(HAS_SWAP_EXISTS_ACTION)
check_swap_exists_action();
- #endif
#if !(defined(AMIGA) || defined(MACOS_X))
/*
* Close stdin and dup it from stderr. Required for GPM to work
--- 2619,2636 ----
{
int i;
! // When getting the ATTENTION prompt here, use a dialog
swap_exists_action = SEA_DIALOG;
!
no_wait_return = TRUE;
i = msg_didany;
set_buflisted(TRUE);
! (void)open_buffer(TRUE, NULL, 0); // create memfile and read file
no_wait_return = FALSE;
msg_didany = i;
TIME_MSG("reading stdin");
!
check_swap_exists_action();
#if !(defined(AMIGA) || defined(MACOS_X))
/*
* Close stdin and dup it from stderr. Required for GPM to work
***************
*** 2741,2756 ****
if (p_fdls >= 0)
curwin->w_p_fdl = p_fdls;
#endif
! #if defined(HAS_SWAP_EXISTS_ACTION)
! /* When getting the ATTENTION prompt here, use a dialog */
swap_exists_action = SEA_DIALOG;
! #endif
set_buflisted(TRUE);
/* create memfile, read file */
(void)open_buffer(FALSE, NULL, 0);
- #if defined(HAS_SWAP_EXISTS_ACTION)
if (swap_exists_action == SEA_QUIT)
{
if (got_int || only_one_window())
--- 2733,2746 ----
if (p_fdls >= 0)
curwin->w_p_fdl = p_fdls;
#endif
! // When getting the ATTENTION prompt here, use a dialog
swap_exists_action = SEA_DIALOG;
!
set_buflisted(TRUE);
/* create memfile, read file */
(void)open_buffer(FALSE, NULL, 0);
if (swap_exists_action == SEA_QUIT)
{
if (got_int || only_one_window())
***************
*** 2768,2774 ****
}
else
handle_swap_exists(NULL);
- #endif
dorewind = TRUE; /* start again */
}
ui_breakcheck();
--- 2758,2763 ----
***************
*** 2865,2877 ****
curwin->w_arg_idx = arg_idx;
/* Edit file from arg list, if there is one. When "Quit" selected
* at the ATTENTION prompt close the window. */
- # ifdef HAS_SWAP_EXISTS_ACTION
swap_exists_did_quit = FALSE;
- # endif
(void)do_ecmd(0, arg_idx < GARGCOUNT
? alist_name(&GARGLIST[arg_idx]) : NULL,
NULL, NULL, ECMD_LASTL, ECMD_HIDE, curwin);
- # ifdef HAS_SWAP_EXISTS_ACTION
if (swap_exists_did_quit)
{
/* abort or quit selected */
--- 2854,2863 ----
***************
*** 2884,2890 ****
win_close(curwin, TRUE);
advance = FALSE;
}
- # endif
if (arg_idx == GARGCOUNT - 1)
arg_had_last = TRUE;
++arg_idx;
--- 2870,2875 ----
***************
*** 3485,3491 ****
mch_exit(0);
}
- #if defined(HAS_SWAP_EXISTS_ACTION)
/*
* Check the result of the ATTENTION dialog:
* When "Quit" selected, exit Vim.
--- 3470,3475 ----
***************
*** 3498,3504 ****
getout(1);
handle_swap_exists(NULL);
}
- #endif
#endif /* NO_VIM_MAIN */
--- 3482,3487 ----
*** ../vim-8.1.1230/src/testdir/test_swap.vim 2019-01-27 14:29:20.724544960
+0100
--- src/testdir/test_swap.vim 2019-04-28 21:50:37.397318520 +0200
***************
*** 164,166 ****
--- 164,222 ----
call delete('Xtest2')
call delete('Xtest3')
endfunc
+
+ func Test_swapfile_delete()
+ autocmd! SwapExists
+ function s:swap_exists()
+ let v:swapchoice = s:swap_choice
+ let s:swapname = v:swapname
+ let s:filename = expand('<afile>')
+ endfunc
+ augroup test_swapfile_delete
+ autocmd!
+ autocmd SwapExists * call s:swap_exists()
+ augroup END
+
+
+ " Create a valid swapfile by editing a file.
+ split XswapfileText
+ call setline(1, ['one', 'two', 'three'])
+ write " file is written, not modified
+ " read the swapfile as a Blob
+ let swapfile_name = swapname('%')
+ let swapfile_bytes = readfile(swapfile_name, 'B')
+
+ " Close the file and recreate the swap file.
+ " Now editing the file will run into the process still existing
+ quit
+ call writefile(swapfile_bytes, swapfile_name)
+ let s:swap_choice = 'e'
+ let s:swapname = ''
+ split XswapfileText
+ quit
+ call assert_equal(swapfile_name, s:swapname)
+
+ " Write the swapfile with a modified PID, now it will be automatically
+ " deleted. Process one should never be Vim.
+ let swapfile_bytes[24:27] = 0z01000000
+ call writefile(swapfile_bytes, swapfile_name)
+ let s:swapname = ''
+ split XswapfileText
+ quit
+ call assert_equal('', s:swapname)
+
+ " Now set the modified flag, the swap file will not be deleted
+ let swapfile_bytes[28 + 80 + 899] = 0x55
+ call writefile(swapfile_bytes, swapfile_name)
+ let s:swapname = ''
+ split XswapfileText
+ quit
+ call assert_equal(swapfile_name, s:swapname)
+
+ call delete('XswapfileText')
+ call delete(swapfile_name)
+ augroup test_swapfile_delete
+ autocmd!
+ augroup END
+ augroup! test_swapfile_delete
+ endfunc
*** ../vim-8.1.1230/runtime/doc/usr_11.txt 2018-05-17 13:42:03.000000000
+0200
--- runtime/doc/usr_11.txt 2019-04-28 21:58:09.667057415 +0200
***************
*** 120,126 ****
USING A SPECIFIC SWAP FILE
If you know which swap file needs to be used, you can recover by giving the
! swap file name. Vim will then finds out the name of the original file from
the swap file.
Example: >
--- 120,126 ----
USING A SPECIFIC SWAP FILE
If you know which swap file needs to be used, you can recover by giving the
! swap file name. Vim will then find out the name of the original file from
the swap file.
Example: >
***************
*** 205,210 ****
--- 205,217 ----
NEWER than swap file! ~
+ NOTE that in the following situation Vim knows the swap file is not useful and
+ will automatically delete it:
+ - The file is a valid swap file (Magic number is correct).
+ - The flag that the file was modified is not set.
+ - The process is not running.
+
+
UNREADABLE SWAP FILE
Sometimes the line
***************
*** 284,289 ****
--- 291,297 ----
'shortmess' option. But it's very unusual that you need this.
For remarks about encryption and the swap file, see |:recover-crypt|.
+ For programatic access to the swap file, see |swapinfo()|.
==============================================================================
*11.4* Further reading
*** ../vim-8.1.1230/src/os_win32.c 2019-04-28 19:46:17.034060084 +0200
--- src/os_win32.c 2019-04-28 22:11:28.811767431 +0200
***************
*** 2903,2908 ****
--- 2903,2925 ----
return (long)GetCurrentProcessId();
}
+ /*
+ * return TRUE if process "pid" is still running
+ */
+ int
+ mch_process_running(pid_t pid)
+ {
+ HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 0, (DWORD)pid);
+ DWORD status = 0;
+ int ret = FALSE;
+
+ if (hProcess == NULL)
+ return FALSE; // might not have access
+ if (GetExitCodeProcess(hProcess, &status) )
+ ret = status == STILL_ACTIVE;
+ CloseHandle(hProcess);
+ return ret;
+ }
/*
* Get name of current directory into buffer 'buf' of length 'len' bytes.
*** ../vim-8.1.1230/src/proto/os_win32.pro 2019-04-28 19:46:17.034060084
+0200
--- src/proto/os_win32.pro 2019-04-28 22:14:17.599153672 +0200
***************
*** 19,24 ****
--- 19,25 ----
int mch_get_user_name(char_u *s, int len);
void mch_get_host_name(char_u *s, int len);
long mch_get_pid(void);
+ int mch_process_running(pid_t pid);
int mch_dirname(char_u *buf, int len);
long mch_getperm(char_u *name);
int mch_setperm(char_u *name, long perm);
*** ../vim-8.1.1230/src/os_unix.c 2019-04-04 20:13:06.001014760 +0200
--- src/os_unix.c 2019-04-28 22:19:41.013860198 +0200
***************
*** 2393,2398 ****
--- 2393,2408 ----
return (long)getpid();
}
+ /*
+ * return TRUE if process "pid" is still running
+ */
+ int
+ mch_process_running(pid_t pid)
+ {
+ // EMX kill() not working correctly, it seems
+ return kill(pid, 0) == 0;
+ }
+
#if !defined(HAVE_STRERROR) && defined(USE_GETCWD)
static char *
strerror(int err)
*** ../vim-8.1.1230/src/proto/os_unix.pro 2019-01-20 15:30:36.893328693
+0100
--- src/proto/os_unix.pro 2019-04-28 22:19:14.453970686 +0200
***************
*** 27,32 ****
--- 27,33 ----
int mch_get_uname(uid_t uid, char_u *s, int len);
void mch_get_host_name(char_u *s, int len);
long mch_get_pid(void);
+ int mch_process_running(pid_t pid);
int mch_dirname(char_u *buf, int len);
int mch_FullName(char_u *fname, char_u *buf, int len, int force);
int mch_isFullName(char_u *fname);
*** ../vim-8.1.1230/src/version.c 2019-04-28 19:46:17.034060084 +0200
--- src/version.c 2019-04-28 22:20:54.909549767 +0200
***************
*** 769,770 ****
--- 769,772 ----
{ /* Add new patch number below this line */
+ /**/
+ 1231,
/**/
--
ARTHUR: What?
BLACK KNIGHT: None shall pass.
ARTHUR: I have no quarrel with you, good Sir knight, but I must cross
this bridge.
BLACK KNIGHT: Then you shall die.
The Quest for the Holy Grail (Monty Python)
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
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 [email protected].
For more options, visit https://groups.google.com/d/optout.