vim-patch:8.1.0353: an "after" directory of a package is appended to 'rtp'

Problem:    An "after" directory of a package is appended to 'rtp', which
            will be after the user's "after" directory. ()
Solution:   Insert the package "after" directory before any other "after"
            directory in 'rtp'. (closes vim/vim#3409)
99396d4cbf
This commit is contained in:
James McCoy
2018-12-29 11:12:18 -05:00
parent 91f40ff284
commit ce4199e8b0
2 changed files with 91 additions and 34 deletions

View File

@@ -2567,14 +2567,19 @@ static int add_pack_dir_to_rtp(char_u *fname)
} }
// Find "ffname" in "p_rtp", ignoring '/' vs '\' differences // Find "ffname" in "p_rtp", ignoring '/' vs '\' differences
// Also stop at the first "after" directory
size_t fname_len = strlen(ffname); size_t fname_len = strlen(ffname);
const char *insp = (const char *)p_rtp;
buf = try_malloc(MAXPATHL); buf = try_malloc(MAXPATHL);
if (buf == NULL) { if (buf == NULL) {
goto theend; goto theend;
} }
while (*insp != NUL) { const char *insp = NULL;
copy_option_part((char_u **)&insp, buf, MAXPATHL, ","); const char *after_insp = NULL;
for (const char *entry = (const char *)p_rtp; *entry != NUL; ) {
const char *cur_entry = entry;
copy_option_part((char_u **)&entry, buf, MAXPATHL, ",");
if (insp == NULL) {
add_pathsep((char *)buf); add_pathsep((char *)buf);
char *const rtp_ffname = fix_fname((char *)buf); char *const rtp_ffname = fix_fname((char *)buf);
if (rtp_ffname == NULL) { if (rtp_ffname == NULL) {
@@ -2583,16 +2588,28 @@ static int add_pack_dir_to_rtp(char_u *fname)
bool match = path_fnamencmp(rtp_ffname, ffname, fname_len) == 0; bool match = path_fnamencmp(rtp_ffname, ffname, fname_len) == 0;
xfree(rtp_ffname); xfree(rtp_ffname);
if (match) { if (match) {
// Insert "ffname" after this entry (and comma).
insp = entry;
}
}
if ((p = (char_u *)strstr((char *)buf, "after")) != NULL
&& p > buf
&& vim_ispathsep(p[-1])
&& (vim_ispathsep(p[5]) || p[5] == NUL || p[5] == ',')) {
if (insp == NULL) {
// Did not find "ffname" before the first "after" directory,
// insert it before this entry.
insp = cur_entry;
}
after_insp = cur_entry;
break; break;
} }
} }
if (*insp == NUL) { if (insp == NULL) {
// not found, append at the end // Both "fname" and "after" not found, append at the end.
insp = (const char *)p_rtp + STRLEN(p_rtp); insp = (const char *)p_rtp + STRLEN(p_rtp);
} else {
// append after the matching directory.
insp--;
} }
// check if rtp/pack/name/start/name/after exists // check if rtp/pack/name/start/name/after exists
@@ -2604,31 +2621,53 @@ static int add_pack_dir_to_rtp(char_u *fname)
const size_t oldlen = STRLEN(p_rtp); const size_t oldlen = STRLEN(p_rtp);
const size_t addlen = STRLEN(fname) + 1; // add one for comma const size_t addlen = STRLEN(fname) + 1; // add one for comma
const size_t new_rtp_len = oldlen + addlen + afterlen + 1; const size_t new_rtp_capacity = oldlen + addlen + afterlen + 1;
// add one for NUL -------------------------------------^ // add one for NUL ------------------------------------------^
char *const new_rtp = try_malloc(new_rtp_len); char *const new_rtp = try_malloc(new_rtp_capacity);
if (new_rtp == NULL) { if (new_rtp == NULL) {
goto theend; goto theend;
} }
const size_t keep = (size_t)(insp - (const char *)p_rtp);
size_t new_rtp_fill = 0; // We now have 'rtp' parts: {keep}{keep_after}{rest}.
// Create new_rtp, first: {keep},{fname}
size_t keep = (size_t)(insp - (const char *)p_rtp);
memmove(new_rtp, p_rtp, keep); memmove(new_rtp, p_rtp, keep);
new_rtp_fill += keep; size_t new_rtp_len = keep;
new_rtp[new_rtp_fill++] = ','; if (*insp == NUL) {
memmove(new_rtp + new_rtp_fill, fname, addlen); new_rtp[new_rtp_len++] = ','; // add comma before
new_rtp_fill += addlen - 1; }
assert(new_rtp[new_rtp_fill] == NUL || new_rtp[new_rtp_fill] == ','); memmove(new_rtp + new_rtp_len, fname, addlen - 1);
new_rtp_len += addlen - 1;
if (*insp != NUL) {
new_rtp[new_rtp_len++] = ','; // add comma after
}
if (afterlen > 0 && after_insp != NULL) {
size_t keep_after = (size_t)(after_insp - (const char *)p_rtp);
// Add to new_rtp: {keep},{fname}{keep_after},{afterdir}
memmove(new_rtp + new_rtp_len, p_rtp + keep, keep_after - keep);
new_rtp_len += keep_after - keep;
memmove(new_rtp + new_rtp_len, afterdir, afterlen - 1);
new_rtp_len += afterlen - 1;
new_rtp[new_rtp_len++] = ',';
keep = keep_after;
}
if (p_rtp[keep] != NUL) { if (p_rtp[keep] != NUL) {
memmove(new_rtp + new_rtp_fill, p_rtp + keep, oldlen - keep + 1); // Append rest: {keep},{fname}{keep_after},{afterdir}{rest}
new_rtp_fill += oldlen - keep; memmove(new_rtp + new_rtp_len, p_rtp + keep, oldlen - keep + 1);
} else {
new_rtp[new_rtp_len] = NUL;
} }
if (afterlen > 0) {
assert(new_rtp[new_rtp_fill] == NUL); if (afterlen > 0 && after_insp == NULL) {
new_rtp[new_rtp_fill++] = ','; // Append afterdir when "after" was not found:
memmove(new_rtp + new_rtp_fill, afterdir, afterlen - 1); // {keep},{fname}{rest},{afterdir}
new_rtp_fill += afterlen - 1; xstrlcat(new_rtp, ",", new_rtp_capacity);
xstrlcat(new_rtp, afterdir, new_rtp_capacity);
} }
new_rtp[new_rtp_fill] = NUL;
set_option_value("rtp", 0L, new_rtp, 0); set_option_value("rtp", 0L, new_rtp, 0);
xfree(new_rtp); xfree(new_rtp);
retval = OK; retval = OK;

View File

@@ -29,6 +29,11 @@ describe('packadd', function()
endfunc endfunc
func Test_packadd() func Test_packadd()
if !exists('s:plugdir')
echomsg 'when running this test manually, call SetUp() first'
return
endif
call mkdir(s:plugdir . '/plugin/also', 'p') call mkdir(s:plugdir . '/plugin/also', 'p')
call mkdir(s:plugdir . '/ftdetect', 'p') call mkdir(s:plugdir . '/ftdetect', 'p')
call mkdir(s:plugdir . '/after', 'p') call mkdir(s:plugdir . '/after', 'p')
@@ -36,6 +41,14 @@ describe('packadd', function()
let rtp = &rtp let rtp = &rtp
filetype on filetype on
let rtp_entries = split(rtp, ',')
for entry in rtp_entries
if entry =~? '\<after\>'
let first_after_entry = entry
break
endif
endfor
exe 'split ' . s:plugdir . '/plugin/test.vim' exe 'split ' . s:plugdir . '/plugin/test.vim'
call setline(1, 'let g:plugin_works = 42') call setline(1, 'let g:plugin_works = 42')
wq wq
@@ -55,7 +68,12 @@ describe('packadd', function()
call assert_true(17, g:ftdetect_works) call assert_true(17, g:ftdetect_works)
call assert_true(len(&rtp) > len(rtp)) call assert_true(len(&rtp) > len(rtp))
call assert_match(Escape(s:plugdir) . '\($\|,\)', &rtp) call assert_match(Escape(s:plugdir) . '\($\|,\)', &rtp)
call assert_match(Escape(expand(s:plugdir . '/after$')), &rtp)
let new_after = match(&rtp, Escape(expand(s:plugdir . '/after') . ','))
let old_after = match(&rtp, ',' . Escape(first_after_entry) . '\>')
call assert_true(new_after > 0, 'rtp is ' . &rtp)
call assert_true(old_after > 0, 'rtp is ' . &rtp)
call assert_true(new_after < old_after, 'rtp is ' . &rtp)
" NOTE: '/.../opt/myte' forwardly matches with '/.../opt/mytest' " NOTE: '/.../opt/myte' forwardly matches with '/.../opt/mytest'
call mkdir(fnamemodify(s:plugdir, ':h') . '/myte', 'p') call mkdir(fnamemodify(s:plugdir, ':h') . '/myte', 'p')