Mercurial > vim
changeset 19185:17d878a2ddaa v8.2.0151
patch 8.2.0151: detecting a script was already sourced is unreliable
Commit: https://github.com/vim/vim/commit/978d170bdce9c0a47e6683cd7c288bc2706f3fff
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Jan 26 17:38:12 2020 +0100
patch 8.2.0151: detecting a script was already sourced is unreliable
Problem: Detecting a script was already sourced is unreliable.
Solution: Do not use the inode number.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 26 Jan 2020 17:45:04 +0100 |
parents | 070b75b91465 |
children | fb5a7c75b07e |
files | src/scriptfile.c src/structs.h src/testdir/test_vim9_script.vim src/version.c |
diffstat | 4 files changed, 13 insertions(+), 39 deletions(-) [+] |
line wrap: on
line diff
--- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -1091,10 +1091,6 @@ do_source( int save_debug_break_level = debug_break_level; int sid; scriptitem_T *si = NULL; -# ifdef UNIX - stat_T st; - int stat_ok; -# endif #endif #ifdef STARTUPTIME struct timeval tv_rel; @@ -1121,26 +1117,17 @@ do_source( #ifdef FEAT_EVAL // See if we loaded this script before. -# ifdef UNIX - stat_ok = (mch_stat((char *)fname_exp, &st) >= 0); -# endif for (sid = script_items.ga_len; sid > 0; --sid) { + // We used to check inode here, but that doesn't work: + // - If a script is edited and written, it may get a different + // inode number, even though to the user it is the same script. + // - If a script is deleted and another script is written, with a + // different name, the inode may be re-used. si = &SCRIPT_ITEM(sid); - if (si->sn_name != NULL) - { -# ifdef UNIX - // Compare dev/ino when possible, it catches symbolic links. Also - // compare file names, the inode may change when the file was - // edited or it may be re-used for another script (esp. in tests). - if ((stat_ok && si->sn_dev_valid) - && (si->sn_dev != st.st_dev || si->sn_ino != st.st_ino)) - continue; -# endif - if (fnamecmp(si->sn_name, fname_exp) == 0) + if (si->sn_name != NULL && fnamecmp(si->sn_name, fname_exp) == 0) // Found it! break; - } } if (sid > 0 && ret_sid != NULL) { @@ -1324,16 +1311,6 @@ do_source( si = &SCRIPT_ITEM(current_sctx.sc_sid); si->sn_name = fname_exp; fname_exp = vim_strsave(si->sn_name); // used for autocmd -# ifdef UNIX - if (stat_ok) - { - si->sn_dev_valid = TRUE; - si->sn_dev = st.st_dev; - si->sn_ino = st.st_ino; - } - else - si->sn_dev_valid = FALSE; -# endif if (ret_sid != NULL) *ret_sid = current_sctx.sc_sid; }
--- a/src/structs.h +++ b/src/structs.h @@ -1665,11 +1665,6 @@ typedef struct int sn_had_command; // TRUE if any command was executed char_u *sn_save_cpo; // 'cpo' value when :vim9script found -# ifdef UNIX - int sn_dev_valid; - dev_t sn_dev; - ino_t sn_ino; -# endif # ifdef FEAT_PROFILE int sn_prof_on; // TRUE when script is/was profiled int sn_pr_force; // forceit: profile functions in this script
--- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -4,7 +4,7 @@ source check.vim " Check that "lines" inside ":def" results in an "error" message. func CheckDefFailure(lines, error) - call writefile(['def! Func()'] + a:lines + ['enddef'], 'Xdef') + call writefile(['def Func()'] + a:lines + ['enddef'], 'Xdef') call assert_fails('so Xdef', a:error, a:lines) call delete('Xdef') endfunc @@ -126,10 +126,10 @@ enddef def Test_return_type_wrong() " TODO: why is ! needed for Mac and FreeBSD? - CheckScriptFailure(['def! Func(): number', 'return "a"', 'enddef'], 'expected number but got string') - CheckScriptFailure(['def! Func(): string', 'return 1', 'enddef'], 'expected string but got number') - CheckScriptFailure(['def! Func(): void', 'return "a"', 'enddef'], 'expected void but got string') - CheckScriptFailure(['def! Func()', 'return "a"', 'enddef'], 'expected void but got string') + CheckScriptFailure(['def Func(): number', 'return "a"', 'enddef'], 'expected number but got string') + CheckScriptFailure(['def Func(): string', 'return 1', 'enddef'], 'expected string but got number') + CheckScriptFailure(['def Func(): void', 'return "a"', 'enddef'], 'expected void but got string') + CheckScriptFailure(['def Func()', 'return "a"', 'enddef'], 'expected void but got string') enddef def Test_try_catch()