]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.0272: autocmd may change cwd after :tcd and :lcd v9.1.0272
authorzeertzjq <zeertzjq@outlook.com>
Sun, 7 Apr 2024 16:16:10 +0000 (18:16 +0200)
committerChristian Brabandt <cb@256bit.org>
Sun, 7 Apr 2024 16:16:10 +0000 (18:16 +0200)
Problem:  Autocommand may change currect directory after :tcd and :lcd.
Solution: Also clear tp_localdir and w_localdir when using aucmd_win.
          (zeertzjq)

closes: #14435

Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/autocmd.c
src/proto/window.pro
src/structs.h
src/testdir/test_autocmd.vim
src/version.c
src/window.c

index b1c74cb853ac401bffc4e9ee799106e343d8861d..666cf45d3033ab339cdb0f11fb25eec38463f5c8 100644 (file)
@@ -1660,6 +1660,11 @@ aucmd_prepbuf(
 
        win_init_popup_win(auc_win, buf);
 
+       // Make sure tp_localdir and globaldir are NULL to avoid a
+       // chdir() in win_enter_ext().
+       // win_init_popup_win() has already set w_localdir to NULL.
+       aco->tp_localdir = curtab->tp_localdir;
+       curtab->tp_localdir = NULL;
        aco->globaldir = globaldir;
        globaldir = NULL;
 
@@ -1773,6 +1778,12 @@ win_found:
        vars_clear(&awp->w_vars->dv_hashtab);  // free all w: variables
        hash_init(&awp->w_vars->dv_hashtab);   // re-use the hashtab
 #endif
+       // If :lcd has been used in the autocommand window, correct current
+       // directory before restoring tp_localdir and globaldir.
+       if (awp->w_localdir != NULL)
+           win_fix_current_dir();
+       vim_free(curtab->tp_localdir);
+       curtab->tp_localdir = aco->tp_localdir;
        vim_free(globaldir);
        globaldir = aco->globaldir;
 
index 9e66db5a7fc07901cf06cc08c9f4bce5aad56373..26c7040b8a1b4d357333f9cfd6d2a441a616b693 100644 (file)
@@ -57,6 +57,7 @@ tabpage_T *win_find_tabpage(win_T *win);
 win_T *win_vert_neighbor(tabpage_T *tp, win_T *wp, int up, long count);
 win_T *win_horz_neighbor(tabpage_T *tp, win_T *wp, int left, long count);
 void win_enter(win_T *wp, int undo_sync);
+void win_fix_current_dir(void);
 win_T *buf_jump_open_win(buf_T *buf);
 win_T *buf_jump_open_tab(buf_T *buf);
 int win_unlisted(win_T *wp);
index 3ce13ff0fb101338e6ca074a25602e739068b9f9..f9a72e1454f05f2f25f9e59be9873c5716724281 100644 (file)
@@ -4397,6 +4397,7 @@ typedef struct
     int                new_curwin_id;      // ID of new curwin
     int                save_prevwin_id;    // ID of saved prevwin
     bufref_T   new_curbuf;         // new curbuf
+    char_u     *tp_localdir;       // saved value of tp_localdir
     char_u     *globaldir;         // saved value of globaldir
     int                save_VIsual_active; // saved VIsual_active
     int                save_State;         // saved State
index 50fdc41dc1500a01985e23c4e18ec2c95fdcb71c..c7d2534a288c8596431fb8c7fc3ca5d9b6978377 100644 (file)
@@ -3727,6 +3727,49 @@ func Test_switch_window_in_autocmd_window()
   call assert_false(bufexists('Xb.txt'))
 endfunc
 
+" Test that using the autocommand window doesn't change current directory.
+func Test_autocmd_window_cwd()
+  let saveddir = getcwd()
+  call mkdir('Xcwd/a/b/c/d', 'pR')
+
+  new Xa.txt
+  tabnew
+  new Xb.txt
+
+  tabprev
+  cd Xcwd
+  call assert_match('/Xcwd$', getcwd())
+  call assert_match('\[global\] .*/Xcwd$', trim(execute('verbose pwd')))
+
+  autocmd BufEnter Xb.txt lcd ./a/b/c/d
+  doautoall BufEnter
+  au! BufEnter
+  call assert_match('/Xcwd$', getcwd())
+  call assert_match('\[global\] .*/Xcwd$', trim(execute('verbose pwd')))
+
+  tabnext
+  cd ./a
+  tcd ./b
+  lcd ./c
+  call assert_match('/Xcwd/a/b/c$', getcwd())
+  call assert_match('\[window\] .*/Xcwd/a/b/c$', trim(execute('verbose pwd')))
+
+  autocmd BufEnter Xa.txt call assert_match('Xcwd/a/b/c$', getcwd())
+  doautoall BufEnter
+  au! BufEnter
+  call assert_match('/Xcwd/a/b/c$', getcwd())
+  call assert_match('\[window\] .*/Xcwd/a/b/c$', trim(execute('verbose pwd')))
+  bwipe!
+  call assert_match('/Xcwd/a/b$', getcwd())
+  call assert_match('\[tabpage\] .*/Xcwd/a/b$', trim(execute('verbose pwd')))
+  bwipe!
+  call assert_match('/Xcwd/a$', getcwd())
+  call assert_match('\[global\] .*/Xcwd/a$', trim(execute('verbose pwd')))
+  bwipe!
+
+  call chdir(saveddir)
+endfunc
+
 func Test_bufwipeout_changes_window()
   " This should not crash, but we don't have any expectations about what
   " happens, changing window in BufWipeout has unpredictable results.
index 3b33ab176f607fa8e7291e57c3064bc8d813e9ad..6d9a18c1092bdfc2c8d462d6274ff3590399560e 100644 (file)
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    272,
 /**/
     271,
 /**/
index 9ffca77c9292ab9889071cdd8b0ecedd0dcd6bbc..7d78b5f29a7852abd08be865b48b0dd50a864e3e 100644 (file)
@@ -4437,8 +4437,7 @@ win_init_popup_win(win_T *wp, buf_T *buf)
     ++buf->b_nwindows;
     win_init_empty(wp); // set cursor and topline to safe values
 
-    // Make sure w_localdir and globaldir are NULL to avoid a chdir() in
-    // win_enter_ext().
+    // Make sure w_localdir is NULL to avoid a chdir() in win_enter_ext().
     VIM_CLEAR(wp->w_localdir);
 }
 
@@ -5445,8 +5444,8 @@ win_enter(win_T *wp, int undo_sync)
  * Used after making another window the current one: change directory if
  * needed.
  */
-    static void
-fix_current_dir(void)
+    void
+win_fix_current_dir(void)
 {
     if (curwin->w_localdir != NULL || curtab->tp_localdir != NULL)
     {
@@ -5567,7 +5566,7 @@ win_enter_ext(win_T *wp, int flags)
     }
 #endif
 
-    fix_current_dir();
+    win_fix_current_dir();
 
 #ifdef FEAT_JOB_CHANNEL
     entering_window(curwin);