vim-patch:8.0.0444: diffpatch fails when the file name has a quote

Problem:    Diffpatch fails when the file name has a quote.
Solution:   Escape the name properly. (zetzei)

a95ab32120
This commit is contained in:
Justin M. Keyes 2018-01-21 10:36:14 +01:00
parent 456cf72974
commit ab279c6fb8
2 changed files with 25 additions and 28 deletions

View File

@ -856,11 +856,12 @@ void ex_diffpatch(exarg_T *eap)
char_u *buf = NULL; char_u *buf = NULL;
win_T *old_curwin = curwin; win_T *old_curwin = curwin;
char_u *newname = NULL; // name of patched file buffer char_u *newname = NULL; // name of patched file buffer
char_u *esc_name = NULL;
#ifdef UNIX #ifdef UNIX
char_u dirbuf[MAXPATHL]; char_u dirbuf[MAXPATHL];
char_u *fullname = NULL; char_u *fullname = NULL;
#endif // ifdef UNIX #endif
// We need two temp file names. // We need two temp file names.
// Name of original temp file. // Name of original temp file.
char_u *tmp_orig = vim_tempname(); char_u *tmp_orig = vim_tempname();
@ -880,21 +881,21 @@ void ex_diffpatch(exarg_T *eap)
#ifdef UNIX #ifdef UNIX
// Get the absolute path of the patchfile, changing directory below. // Get the absolute path of the patchfile, changing directory below.
fullname = (char_u *)FullName_save((char *)eap->arg, FALSE); fullname = (char_u *)FullName_save((char *)eap->arg, false);
#endif // ifdef UNIX #endif
esc_name = vim_strsave_shellescape(
#ifdef UNIX #ifdef UNIX
size_t buflen = STRLEN(tmp_orig) fullname != NULL ? fullname :
+ (fullname != NULL ? STRLEN(fullname) : STRLEN(eap->arg)) #endif
+ STRLEN(tmp_new) + 16; eap->arg, true, true);
#else if (esc_name == NULL) {
size_t buflen = STRLEN(tmp_orig) + (STRLEN(eap->arg)) + STRLEN(tmp_new) + 16; goto theend;
#endif // ifdef UNIX }
size_t buflen = STRLEN(tmp_orig) + STRLEN(esc_name) + STRLEN(tmp_new) + 16;
buf = xmalloc(buflen); buf = xmalloc(buflen);
#ifdef UNIX #ifdef UNIX
// Temporarily chdir to /tmp, to avoid patching files in the current // Temporarily chdir to /tmp, to avoid patching files in the current
// directory when the patch file contains more than one patch. When we // directory when the patch file contains more than one patch. When we
// have our own temp dir use that instead, it will be cleaned up when we // have our own temp dir use that instead, it will be cleaned up when we
@ -911,26 +912,21 @@ void ex_diffpatch(exarg_T *eap)
os_chdir(tempdir); os_chdir(tempdir);
shorten_fnames(TRUE); shorten_fnames(TRUE);
} }
#endif // ifdef UNIX #endif
if (*p_pex != NUL) { if (*p_pex != NUL) {
// Use 'patchexpr' to generate the new file. // Use 'patchexpr' to generate the new file.
#ifdef UNIX #ifdef UNIX
eval_patch((char *) tmp_orig, eval_patch((char *)tmp_orig,
(char *) (fullname != NULL ? fullname : eap->arg), (char *)(fullname != NULL ? fullname : eap->arg),
(char *) tmp_new); (char *)tmp_new);
#else #else
eval_patch((char *) tmp_orig, (char *) eap->arg, (char *) tmp_new); eval_patch((char *)tmp_orig, (char *)eap->arg, (char *)tmp_new);
#endif // ifdef UNIX #endif
} else { } else {
// Build the patch command and execute it. Ignore errors. // Build the patch command and execute it. Ignore errors.
#ifdef UNIX vim_snprintf((char *)buf, buflen, "patch -o %s %s < %s",
vim_snprintf((char *)buf, buflen, "patch -o %s %s < '%s'", tmp_new, tmp_orig, esc_name);
tmp_new, tmp_orig, fullname != NULL ? fullname : eap->arg);
#else
vim_snprintf((char *)buf, buflen, "patch -o %s %s < \"%s\"",
tmp_new, tmp_orig, eap->arg);
#endif // ifdef UNIX
block_autocmds(); // Avoid ShellCmdPost stuff block_autocmds(); // Avoid ShellCmdPost stuff
(void)call_shell(buf, kShellOptFilter, NULL); (void)call_shell(buf, kShellOptFilter, NULL);
unblock_autocmds(); unblock_autocmds();
@ -943,7 +939,7 @@ void ex_diffpatch(exarg_T *eap)
} }
shorten_fnames(TRUE); shorten_fnames(TRUE);
} }
#endif // ifdef UNIX #endif
// patch probably has written over the screen // patch probably has written over the screen
redraw_later(CLEAR); redraw_later(CLEAR);
@ -1012,7 +1008,8 @@ theend:
xfree(buf); xfree(buf);
#ifdef UNIX #ifdef UNIX
xfree(fullname); xfree(fullname);
#endif // ifdef UNIX #endif
xfree(esc_name);
} }
/// Split the window and edit another file, setting options to show the diffs. /// Split the window and edit another file, setting options to show the diffs.
@ -1163,7 +1160,7 @@ void ex_diffoff(exarg_T *eap)
free_string_option(wp->w_p_fdm); free_string_option(wp->w_p_fdm);
wp->w_p_fdm = vim_strsave(*wp->w_p_fdm_save wp->w_p_fdm = vim_strsave(*wp->w_p_fdm_save
? wp->w_p_fdm_save ? wp->w_p_fdm_save
: (char_u*)"manual"); : (char_u *)"manual");
if (wp->w_p_fdc == diff_foldcolumn) { if (wp->w_p_fdc == diff_foldcolumn) {
wp->w_p_fdc = wp->w_p_fdc_save; wp->w_p_fdc = wp->w_p_fdc_save;
} }

View File

@ -502,7 +502,7 @@ func Test_diffpatch()
new new
call assert_fails('diffpatch Xpatch', 'E816:') call assert_fails('diffpatch Xpatch', 'E816:')
for name in ['Xpatch', 'Xpatch$HOME'] for name in ['Xpatch', 'Xpatch$HOME', 'Xpa''tch']
call setline(1, ['1', '2', '3']) call setline(1, ['1', '2', '3'])
if name != 'Xpatch' if name != 'Xpatch'
call rename('Xpatch', name) call rename('Xpatch', name)