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()
--- a/src/version.c
+++ b/src/version.c
@@ -743,6 +743,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    151,
+/**/
     150,
 /**/
     149,