changeset 3490:8101253704f6 v7.3.509

updated for version 7.3.509 Problem: ":vimgrep" fails when 'autochdir' is set. Solution: A more generic solution for changing directory. (Ben Fritz)
author Bram Moolenaar <bram@vim.org>
date Wed, 25 Apr 2012 18:57:21 +0200
parents f53d1d03019a
children 5af3c91be43f
files src/quickfix.c src/version.c
diffstat 2 files changed, 74 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -130,9 +130,10 @@ static void	qf_set_title __ARGS((qf_info
 static void	qf_fill_buffer __ARGS((qf_info_T *qi));
 #endif
 static char_u	*get_mef_name __ARGS((void));
-static buf_T	*load_dummy_buffer __ARGS((char_u *fname));
-static void	wipe_dummy_buffer __ARGS((buf_T *buf));
-static void	unload_dummy_buffer __ARGS((buf_T *buf));
+static void	restore_start_dir __ARGS((char_u *dirname_start));
+static buf_T	*load_dummy_buffer __ARGS((char_u *fname, char_u *dirname_start, char_u *resulting_dir));
+static void	wipe_dummy_buffer __ARGS((buf_T *buf, char_u *dirname_start));
+static void	unload_dummy_buffer __ARGS((buf_T *buf, char_u *dirname_start));
 static qf_info_T *ll_get_or_alloc_list __ARGS((win_T *));
 
 /* Quickfix window check helper macro */
@@ -3237,19 +3238,7 @@ ex_vimgrep(eap)
 
 	    /* Load file into a buffer, so that 'fileencoding' is detected,
 	     * autocommands applied, etc. */
-	    buf = load_dummy_buffer(fname);
-
-	    /* When autocommands changed directory: go back.  We assume it was
-	     * ":lcd %:p:h". */
-	    mch_dirname(dirname_now, MAXPATHL);
-	    if (STRCMP(dirname_start, dirname_now) != 0)
-	    {
-		exarg_T ea;
-
-		ea.arg = dirname_start;
-		ea.cmdidx = CMD_lcd;
-		ex_cd(&ea);
-	    }
+	    buf = load_dummy_buffer(fname, dirname_start, dirname_now);
 
 	    p_mls = save_mls;
 #if defined(FEAT_AUTOCMD) && defined(FEAT_SYN_HL)
@@ -3320,7 +3309,7 @@ ex_vimgrep(eap)
 		{
 		    /* Never keep a dummy buffer if there is another buffer
 		     * with the same name. */
-		    wipe_dummy_buffer(buf);
+		    wipe_dummy_buffer(buf, dirname_start);
 		    buf = NULL;
 		}
 		else if (!cmdmod.hide
@@ -3336,12 +3325,12 @@ ex_vimgrep(eap)
 		     * many swap files. */
 		    if (!found_match)
 		    {
-			wipe_dummy_buffer(buf);
+			wipe_dummy_buffer(buf, dirname_start);
 			buf = NULL;
 		    }
 		    else if (buf != first_match_buf || (flags & VGR_NOJUMP))
 		    {
-			unload_dummy_buffer(buf);
+			unload_dummy_buffer(buf, dirname_start);
 			buf = NULL;
 		    }
 		}
@@ -3487,13 +3476,48 @@ skip_vimgrep_pat(p, s, flags)
 }
 
 /*
- * Load file "fname" into a dummy buffer and return the buffer pointer.
+ * Restore current working directory to "dirname_start" if they differ, taking
+ * into account whether it is set locally or globally.
+ */
+    static void
+restore_start_dir(dirname_start)
+    char_u	*dirname_start;
+{
+    char_u *dirname_now = alloc(MAXPATHL);
+
+    if (NULL != dirname_now)
+    {
+	mch_dirname(dirname_now, MAXPATHL);
+	if (STRCMP(dirname_start, dirname_now) != 0)
+	{
+	    /* If the directory has changed, change it back by building up an
+	     * appropriate ex command and executing it. */
+	    exarg_T ea;
+
+	    ea.arg = dirname_start;
+	    ea.cmdidx = (curwin->w_localdir == NULL) ? CMD_cd : CMD_lcd;
+	    ex_cd(&ea);
+	}
+    }
+}
+
+/*
+ * Load file "fname" into a dummy buffer and return the buffer pointer,
+ * placing the directory resulting from the buffer load into the
+ * "resulting_dir" pointer. "resulting_dir" must be allocated by the caller
+ * prior to calling this function. Restores directory to "dirname_start" prior
+ * to returning, if autocmds or the 'autochdir' option have changed it.
+ *
+ * If creating the dummy buffer does not fail, must call unload_dummy_buffer()
+ * or wipe_dummy_buffer() later!
+ *
  * Returns NULL if it fails.
- * Must call unload_dummy_buffer() or wipe_dummy_buffer() later!
  */
     static buf_T *
-load_dummy_buffer(fname)
+load_dummy_buffer(fname, dirname_start, resulting_dir)
     char_u	*fname;
+    char_u	*dirname_start;  /* in: old directory */
+    char_u	*resulting_dir;  /* out: new directory */
 {
     buf_T	*newbuf;
     buf_T	*newbuf_to_wipe = NULL;
@@ -3548,22 +3572,33 @@ load_dummy_buffer(fname)
 	    wipe_buffer(newbuf_to_wipe, FALSE);
     }
 
+    /*
+     * When autocommands/'autochdir' option changed directory: go back.
+     * Let the caller know what the resulting dir was first, in case it is
+     * important.
+     */
+    mch_dirname(resulting_dir, MAXPATHL);
+    restore_start_dir(dirname_start);
+
     if (!buf_valid(newbuf))
 	return NULL;
     if (failed)
     {
-	wipe_dummy_buffer(newbuf);
+	wipe_dummy_buffer(newbuf, dirname_start);
 	return NULL;
     }
     return newbuf;
 }
 
 /*
- * Wipe out the dummy buffer that load_dummy_buffer() created.
+ * Wipe out the dummy buffer that load_dummy_buffer() created. Restores
+ * directory to "dirname_start" prior to returning, if autocmds or the
+ * 'autochdir' option have changed it.
  */
     static void
-wipe_dummy_buffer(buf)
+wipe_dummy_buffer(buf, dirname_start)
     buf_T	*buf;
+    char_u	*dirname_start;
 {
     if (curbuf != buf)		/* safety check */
     {
@@ -3583,18 +3618,28 @@ wipe_dummy_buffer(buf)
 	 * new aborting error, interrupt, or uncaught exception. */
 	leave_cleanup(&cs);
 #endif
+	/* When autocommands/'autochdir' option changed directory: go back. */
+	restore_start_dir(dirname_start);
     }
 }
 
 /*
- * Unload the dummy buffer that load_dummy_buffer() created.
+ * Unload the dummy buffer that load_dummy_buffer() created. Restores
+ * directory to "dirname_start" prior to returning, if autocmds or the
+ * 'autochdir' option have changed it.
  */
     static void
-unload_dummy_buffer(buf)
+unload_dummy_buffer(buf, dirname_start)
     buf_T	*buf;
+    char_u	*dirname_start;
 {
     if (curbuf != buf)		/* safety check */
+    {
 	close_buffer(NULL, buf, DOBUF_UNLOAD, FALSE);
+
+	/* When autocommands/'autochdir' option changed directory: go back. */
+	restore_start_dir(dirname_start);
+    }
 }
 
 #if defined(FEAT_EVAL) || defined(PROTO)
--- a/src/version.c
+++ b/src/version.c
@@ -715,6 +715,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    509,
+/**/
     508,
 /**/
     507,