]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.2.4850: mksession mixes up "tabpages" and "curdir" arguments v8.2.4850
authorLemonBoy <thatlemon@gmail.com>
Sat, 30 Apr 2022 15:10:27 +0000 (16:10 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 30 Apr 2022 15:10:27 +0000 (16:10 +0100)
Problem:    Mksession mixes up "tabpages" and "curdir" arguments.
Solution:   Correct logic for storing tabpage in session. (closes #10312)

src/session.c
src/testdir/test_mksession.vim
src/version.c

index d80f11ff7c65f659b2f9da1cb0644afcf531542d..d91ae198186785f264ded95ae14e0aa79f5cf6b0 100644 (file)
@@ -623,13 +623,13 @@ makeopens(
     win_T      *wp;
     char_u     *sname;
     win_T      *edited_win = NULL;
-    int                tabnr;
     int                restore_stal = FALSE;
     win_T      *tab_firstwin;
     frame_T    *tab_topframe;
     int                cur_arg_idx = 0;
     int                next_arg_idx = 0;
     int                ret = FAIL;
+    tabpage_T  *tp;
 #ifdef FEAT_TERMINAL
     hashtab_T  terminal_bufs;
 
@@ -755,18 +755,11 @@ makeopens(
        restore_stal = TRUE;
     }
 
-    // May repeat putting Windows for each tab, when "tabpages" is in
-    // 'sessionoptions'.
-    // Don't use goto_tabpage(), it may change directory and trigger
-    // autocommands.
-    tab_firstwin = firstwin;   // first window in tab page "tabnr"
-    tab_topframe = topframe;
     if ((ssop_flags & SSOP_TABPAGES))
     {
-       tabpage_T *tp;
-
-       // Similar to ses_win_rec() below, populate the tab pages first so
-       // later local options won't be copied to the new tabs.
+       // "tabpages" is in 'sessionoptions': Similar to ses_win_rec() below,
+       // populate the tab pages first so later local options won't be copied
+       // to the new tabs.
        FOR_ALL_TABPAGES(tp)
            // Use `bufhidden=wipe` to remove empty "placeholder" buffers once
            // they are not needed. This prevents creating extra buffers (see
@@ -777,18 +770,20 @@ makeopens(
        if (first_tabpage->tp_next != NULL && put_line(fd, "tabrewind") == FAIL)
            goto fail;
     }
-    for (tabnr = 1; ; ++tabnr)
+
+    // Assume "tabpages" is in 'sessionoptions'.  If not then we only do
+    // "curtab" and bail out of the loop.
+    FOR_ALL_TABPAGES(tp)
     {
-       tabpage_T *tp = NULL;
        int     need_tabnext = FALSE;
        int     cnr = 1;
 
+       // May repeat putting Windows for each tab, when "tabpages" is in
+       // 'sessionoptions'.
+       // Don't use goto_tabpage(), it may change directory and trigger
+       // autocommands.
        if ((ssop_flags & SSOP_TABPAGES))
        {
-           tp = find_tabpage(tabnr);
-
-           if (tp == NULL)
-               break;          // done all tab pages
            if (tp == curtab)
            {
                tab_firstwin = firstwin;
@@ -799,9 +794,15 @@ makeopens(
                tab_firstwin = tp->tp_firstwin;
                tab_topframe = tp->tp_topframe;
            }
-           if (tabnr > 1)
+           if (tp != first_tabpage)
                need_tabnext = TRUE;
        }
+       else
+       {
+           tp = curtab;
+           tab_firstwin = firstwin;
+           tab_topframe = topframe;
+       }
 
        // Before creating the window layout, try loading one file.  If this
        // is aborted we don't end up with a number of useless windows.
@@ -893,11 +894,11 @@ makeopens(
        // Restore the tab-local working directory if specified
        // Do this before the windows, so that the window-local directory can
        // override the tab-local directory.
-       if (tp != NULL && tp->tp_localdir != NULL && ssop_flags & SSOP_CURDIR)
+       if ((ssop_flags & SSOP_CURDIR) && tp->tp_localdir != NULL)
        {
            if (fputs("tcd ", fd) < 0
-                   || ses_put_fname(fd, tp->tp_localdir, &ssop_flags) == FAIL
-                   || put_eol(fd) == FAIL)
+                    || ses_put_fname(fd, tp->tp_localdir, &ssop_flags) == FAIL
+                    || put_eol(fd) == FAIL)
                goto fail;
            did_lcd = TRUE;
        }
index 247d1797d1c2e8dfd36bcbb8cc96e6dc67667275..ab224c4e8d6b2af42fd0a4175f6a3c07b29f8d71 100644 (file)
@@ -865,6 +865,34 @@ func Test_mksession_sesdir()
   call delete('Xproj', 'rf')
 endfunc
 
+" Test for saving and restoring the tab-local working directory when there is
+" only a single tab and 'tabpages' is not in 'sessionoptions'.
+func Test_mksession_tcd_single_tabs()
+  only | tabonly
+
+  let save_cwd = getcwd()
+  set sessionoptions-=tabpages
+  set sessionoptions+=curdir
+  call mkdir('Xtopdir1')
+  call mkdir('Xtopdir2')
+
+  " There are two tab pages, the current one has local cwd set to 'Xtopdir2'.
+  exec 'tcd ' .. save_cwd .. '/Xtopdir1'
+  tabnew
+  exec 'tcd ' .. save_cwd .. '/Xtopdir2'
+  mksession! Xtest_tcd_single
+
+  source Xtest_tcd_single
+  call assert_equal(2, haslocaldir())
+  call assert_equal('Xtopdir2', fnamemodify(getcwd(-1, 0), ':t'))
+  %bwipe
+
+  set sessionoptions&
+  call chdir(save_cwd)
+  call delete('Xtopdir1', 'rf')
+  call delete('Xtopdir2', 'rf')
+endfunc
+
 " Test for storing the 'lines' and 'columns' settings
 func Test_mksession_resize()
   mksession! Xtest_mks1.out
index 961016c34557a2ab1ed77966070a485b41412df1..0e08c297e942d199e848ec89850d9812011636ae 100644 (file)
@@ -746,6 +746,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4850,
 /**/
     4849,
 /**/