summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErnie Rael <errael@raelity.com>2024-04-16 22:11:56 +0200
committerChristian Brabandt <cb@256bit.org>2024-04-16 22:11:56 +0200
commit9a90179a11b433fcbcf587182032222e229c6d75 (patch)
tree19109477719add748d5f2b2dccdc3bca3e69dd3b
parentd1068a2bb09fd3b9d117d832105bf10dd5e48e2f (diff)
patch 9.1.0338: Vim9: import through symlinks not correctly handledv9.1.0338
Problem: Vim9: import through symlinks not correctly handled Solution: Check for script being a symlink but only once (Ernie Rael) closes: #14565 Signed-off-by: Ernie Rael <errael@raelity.com> Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
-rw-r--r--src/proto/scriptfile.pro1
-rw-r--r--src/scriptfile.c37
-rw-r--r--src/structs.h1
-rw-r--r--src/testdir/test_vim9_import.vim27
-rw-r--r--src/version.c2
-rw-r--r--src/vim9expr.c3
6 files changed, 71 insertions, 0 deletions
diff --git a/src/proto/scriptfile.pro b/src/proto/scriptfile.pro
index dbcc849353..c8ff04a116 100644
--- a/src/proto/scriptfile.pro
+++ b/src/proto/scriptfile.pro
@@ -9,6 +9,7 @@ void ex_runtime(exarg_T *eap);
void set_context_in_runtime_cmd(expand_T *xp, char_u *arg);
int find_script_by_name(char_u *name);
int get_new_scriptitem_for_fname(int *error, char_u *fname);
+void check_script_symlink(int sid);
int do_in_path(char_u *path, char *prefix, char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie);
int do_in_runtimepath(char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie);
int source_runtime(char_u *name, int flags);
diff --git a/src/scriptfile.c b/src/scriptfile.c
index 109e13e5c6..cc76260410 100644
--- a/src/scriptfile.c
+++ b/src/scriptfile.c
@@ -405,6 +405,43 @@ get_new_scriptitem_for_fname(int *error, char_u *fname)
return sid;
}
+/*
+ * If the script for "sid" is a symlink and "sn_source_sid" is not set
+ * then initialize it. A new script_item is created if needed.
+ */
+ void
+check_script_symlink(int sid)
+{
+ scriptitem_T *si = SCRIPT_ITEM(sid);
+ if (si->sn_syml_checked || si->sn_sourced_sid > 0)
+ return;
+ si->sn_syml_checked = TRUE;
+
+ // If fname is a symbolic link, create an script_item for the real file.
+
+ char_u *real_fname = fix_fname(si->sn_name);
+ if (real_fname != NULL && STRCMP(real_fname, si->sn_name) != 0)
+ {
+ int real_sid = find_script_by_name(real_fname);
+ int error2 = OK;
+ int new_sid = FALSE;
+ if (real_sid < 0)
+ {
+ real_sid = get_new_scriptitem_for_fname(&error2, real_fname);
+ new_sid = TRUE;
+ }
+ if (error2 == OK)
+ {
+ si = SCRIPT_ITEM(sid);
+ si->sn_sourced_sid = real_sid;
+ if (new_sid)
+ SCRIPT_ITEM(real_sid)->sn_import_autoload
+ = si->sn_import_autoload;
+ }
+ }
+ vim_free(real_fname);
+}
+
static void
find_script_callback(char_u *fname, void *cookie)
{
diff --git a/src/structs.h b/src/structs.h
index f9a72e1454..36339c4347 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -2131,6 +2131,7 @@ typedef struct
int sn_state; // SN_STATE_ values
char_u *sn_save_cpo; // 'cpo' value when :vim9script found
char sn_is_vimrc; // .vimrc file, do not restore 'cpo'
+ char sn_syml_checked;// flag: this has been checked for sym link
// for a Vim9 script under "rtp/autoload/" this is "dir#scriptname#"
char_u *sn_autoload_prefix;
diff --git a/src/testdir/test_vim9_import.vim b/src/testdir/test_vim9_import.vim
index 67b67595f5..156b035d48 100644
--- a/src/testdir/test_vim9_import.vim
+++ b/src/testdir/test_vim9_import.vim
@@ -2930,6 +2930,33 @@ def Test_vim9_import_symlink()
unlet g:resultValue
&rtp = save_rtp
delete('Xfrom', 'rf')
+
+ # Access item from :def imported through symbolic linked directory. #14536
+ mkdir('Xto/real_dir', 'pR')
+ lines =<< trim END
+ vim9script
+ export const val = 17
+ export def F(): number
+ return 23
+ enddef
+ END
+ writefile(lines, 'Xto/real_dir/real_file.vim')
+ system('ln -s real_dir Xto/syml_dir')
+ defer delete('Xto/syml_dir')
+ lines =<< trim END
+ vim9script
+ import autoload './Xto/syml_dir/real_file.vim'
+
+ def Fmain()
+ assert_equal(17, real_file.val)
+ enddef
+ def F2()
+ assert_equal(23, real_file.F())
+ enddef
+ Fmain()
+ F2()
+ END
+ v9.CheckScriptSuccess(lines)
endif
enddef
diff --git a/src/version.c b/src/version.c
index 802addc308..d11f808484 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 338,
+/**/
337,
/**/
336,
diff --git a/src/vim9expr.c b/src/vim9expr.c
index ac4d836229..8c412b876d 100644
--- a/src/vim9expr.c
+++ b/src/vim9expr.c
@@ -546,6 +546,9 @@ compile_load_scriptvar(
int done = FALSE;
int res = OK;
+ check_script_symlink(import->imp_sid);
+ import_check_sourced_sid(&import->imp_sid);
+
// Need to lookup the member.
if (*p != '.')
{