2014-12-25 12:50:28 -07:00
#!/usr/bin/env bash
set -e
2015-07-22 08:00:17 -07:00
set -u
2016-08-14 05:19:46 -07:00
# Use privileged mode, which e.g. skips using CDPATH.
2016-08-11 05:09:50 -07:00
set -p
2014-11-21 06:39:35 -07:00
2016-09-12 04:40:55 -07:00
readonly NVIM_SOURCE_DIR = " ${ NVIM_SOURCE_DIR :- $( cd " $( dirname " ${ BASH_SOURCE [0] } " ) /.. " && pwd ) } "
readonly VIM_SOURCE_DIR_DEFAULT = " ${ NVIM_SOURCE_DIR } /.vim-src "
2015-03-05 19:49:03 -07:00
readonly VIM_SOURCE_DIR = " ${ VIM_SOURCE_DIR :- ${ VIM_SOURCE_DIR_DEFAULT } } "
readonly BASENAME = " $( basename " ${ 0 } " ) "
2016-02-08 16:05:49 -07:00
readonly BRANCH_PREFIX = "vim-"
2014-11-21 06:39:35 -07:00
2016-01-23 04:05:04 -07:00
CREATED_FILES = ( )
2015-01-07 12:52:10 -07:00
usage( ) {
2017-12-25 19:38:42 -07:00
echo "Port Vim patches to Neovim"
2015-03-05 19:49:03 -07:00
echo "https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-vim"
echo
2015-07-22 08:00:17 -07:00
echo " Usage: ${ BASENAME } [-h | -l | -p vim-revision | -r pr-number] "
2015-03-05 19:49:03 -07:00
echo
echo "Options:"
2015-07-22 08:00:17 -07:00
echo " -h Show this message and exit."
2017-12-25 19:38:42 -07:00
echo " -l List missing Vim patches."
echo " -L List missing Vim patches (for scripts)."
echo " -M List all merged patch-numbers (at current v:version)."
echo " -p {vim-revision} Download and generate a Vim patch. vim-revision"
echo " can be a Vim version (8.0.xxx) or a Git hash."
echo " -P {vim-revision} Download, generate and apply a Vim patch."
echo " -g {vim-revision} Download a Vim patch."
echo " -s Create a vim-patch pull request."
echo " -r {pr-number} Review a vim-patch pull request."
echo ' -V Clone the Vim source code to $VIM_SOURCE_DIR.'
2015-03-05 19:49:03 -07:00
echo
2017-12-10 17:58:55 -07:00
echo ' $VIM_SOURCE_DIR controls where Vim sources are found'
echo " (default: ' ${ VIM_SOURCE_DIR_DEFAULT } ') "
2015-01-07 12:52:10 -07:00
}
2018-03-08 04:58:16 -07:00
msg_ok( ) {
2018-06-19 06:27:32 -07:00
printf '\e[32m✔\e[0m %s\n' " $@ "
2018-03-08 04:58:16 -07:00
}
msg_err( ) {
2018-06-19 06:27:32 -07:00
printf '\e[31m✘\e[0m %s\n' " $@ "
2018-03-08 04:58:16 -07:00
}
2015-07-22 08:00:17 -07:00
# Checks if a program is in the user's PATH, and is executable.
check_executable( ) {
2016-05-16 20:41:41 -07:00
test -x " $( command -v " ${ 1 } " ) "
}
require_executable( ) {
if ! check_executable " ${ 1 } " ; then
2015-07-22 08:00:17 -07:00
>& 2 echo " ${ BASENAME } : ' ${ 1 } ' not found in PATH or not executable. "
exit 1
fi
}
2016-01-23 04:05:04 -07:00
clean_files( ) {
if [ [ ${# CREATED_FILES [@] } -eq 0 ] ] ; then
return
fi
echo
echo "Created files:"
local file
2016-05-11 15:09:39 -07:00
for file in " ${ CREATED_FILES [@] } " ; do
2016-01-23 04:05:04 -07:00
echo " • ${ file } "
done
read -p "Delete these files (Y/n)? " -n 1 -r reply
echo
2016-12-21 19:17:01 -07:00
if [ [ " ${ reply } " = = n ] ] ; then
2016-01-23 04:05:04 -07:00
echo "You can use 'git clean' to remove these files when you're done."
2016-12-21 19:17:01 -07:00
else
rm -- " ${ CREATED_FILES [@] } "
2016-01-23 04:05:04 -07:00
fi
}
2015-01-07 12:52:10 -07:00
get_vim_sources( ) {
2016-05-16 20:41:41 -07:00
require_executable git
2015-07-22 08:00:17 -07:00
2015-01-07 12:52:10 -07:00
if [ [ ! -d ${ VIM_SOURCE_DIR } ] ] ; then
2018-03-08 04:58:16 -07:00
echo " Cloning Vim into: ${ VIM_SOURCE_DIR } "
2016-04-08 10:54:50 -07:00
git clone https://github.com/vim/vim.git " ${ VIM_SOURCE_DIR } "
2016-01-08 17:12:36 -07:00
cd " ${ VIM_SOURCE_DIR } "
2015-01-07 12:52:10 -07:00
else
2018-08-20 08:41:00 -07:00
cd " ${ VIM_SOURCE_DIR } "
2018-08-20 23:37:49 -07:00
if ! [ -d ".git" ] \
&& ! [ " $( git rev-parse --show-toplevel) " = " ${ VIM_SOURCE_DIR } " ] ; then
2018-03-08 04:58:16 -07:00
msg_err " ${ VIM_SOURCE_DIR } does not appear to be a git repository. "
2015-08-18 21:21:11 -07:00
echo " Please remove it and try again."
exit 1
fi
2018-03-08 04:58:16 -07:00
echo " Updating Vim sources: ${ VIM_SOURCE_DIR } "
2018-09-30 12:05:26 -07:00
git pull --ff &&
2018-03-08 04:58:16 -07:00
msg_ok "Updated Vim sources." ||
msg_err "Could not update Vim sources; ignoring error."
2015-01-07 12:52:10 -07:00
fi
}
2015-07-22 08:00:17 -07:00
commit_message( ) {
2017-12-16 19:42:08 -07:00
if [ [ -n " $vim_tag " ] ] ; then
2018-03-24 14:42:13 -07:00
printf '%s\n%s' " ${ vim_message } " " ${ vim_commit_url } "
2017-12-16 19:42:08 -07:00
else
2018-03-24 14:42:13 -07:00
printf 'vim-patch:%s\n\n%s\n%s' " $vim_version " " $vim_message " " $vim_commit_url "
2017-12-16 19:42:08 -07:00
fi
2015-07-22 08:00:17 -07:00
}
2016-04-21 18:56:20 -07:00
find_git_remote( ) {
2016-04-24 04:49:00 -07:00
git remote -v \
2016-06-01 12:02:20 -07:00
| awk '$2 ~ /github.com[:\/]neovim\/neovim/ && $3 == "(fetch)" {print $1; exit}'
2016-04-21 18:56:20 -07:00
}
2015-07-22 08:00:17 -07:00
assign_commit_details( ) {
2015-03-05 19:49:03 -07:00
if [ [ ${ 1 } = ~ [ 0-9] \. [ 0-9] \. [ 0-9] { 3,4} ] ] ; then
2015-08-25 23:07:31 -07:00
# Interpret parameter as version number (tag).
2015-01-07 12:52:10 -07:00
vim_version = " ${ 1 } "
2015-08-25 23:07:31 -07:00
vim_tag = " v ${ 1 } "
2016-01-23 04:05:04 -07:00
vim_commit = $( cd " ${ VIM_SOURCE_DIR } " \
2016-05-11 15:09:39 -07:00
&& git log -1 --format= "%H" " ${ vim_tag } " )
2017-12-16 19:42:08 -07:00
local munge_commit_line = true
2015-01-07 12:52:10 -07:00
else
# Interpret parameter as commit hash.
2017-03-21 03:28:13 -07:00
vim_version = " ${ 1 : 0 : 12 } "
2017-12-16 19:42:08 -07:00
vim_tag =
2016-01-23 04:05:04 -07:00
vim_commit = $( cd " ${ VIM_SOURCE_DIR } " \
2016-05-11 15:09:39 -07:00
&& git log -1 --format= "%H" " ${ vim_version } " )
2017-12-16 19:42:08 -07:00
local munge_commit_line = false
2015-01-07 12:52:10 -07:00
fi
2015-08-25 23:07:31 -07:00
vim_commit_url = " https://github.com/vim/vim/commit/ ${ vim_commit } "
2016-01-23 13:45:21 -07:00
vim_message = " $( cd " ${ VIM_SOURCE_DIR } " \
2016-02-16 16:18:01 -07:00
&& git log -1 --pretty= 'format:%B' " ${ vim_commit } " \
2018-08-09 12:36:05 -07:00
| sed -e 's/\(#[0-9]\{1,\}\)/vim\/vim\1/g' ) "
2017-12-16 19:42:08 -07:00
if [ [ ${ munge_commit_line } = = "true" ] ] ; then
2015-07-22 08:00:17 -07:00
# Remove first line of commit message.
2017-12-16 19:42:08 -07:00
vim_message = " $( echo " ${ vim_message } " | sed -e '1s/^patch /vim-patch:/' ) "
2015-07-22 08:00:17 -07:00
fi
2016-01-23 13:45:21 -07:00
patch_file = " vim- ${ vim_version } .patch "
2015-07-22 08:00:17 -07:00
}
2016-10-19 06:43:04 -07:00
# Patch surgery
2016-09-12 04:40:55 -07:00
preprocess_patch( ) {
local file = " $1 "
2016-09-13 03:18:07 -07:00
local nvim = "nvim -u NORC -i NONE --headless"
2016-09-12 04:40:55 -07:00
# Remove *.proto, Make*, gui_*, some if_*
2016-11-17 09:27:13 -07:00
local na_src = 'proto\|Make*\|gui_*\|if_lua\|if_mzsch\|if_olepp\|if_ole\|if_perl\|if_py\|if_ruby\|if_tcl\|if_xcmdsrv'
2017-09-27 05:20:43 -07:00
2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/\S*\<\%(testdir/\)\@<!\%(' ${ na_src } '\)@norm! d/\v(^diff)|%$
' +w +q " $file "
2016-09-12 04:40:55 -07:00
2018-11-04 14:59:39 -07:00
# Remove unwanted Vim doc files.
local na_doc = 'channel\.txt\|netbeans\.txt\|os_\w\+\.txt\|term\.txt\|todo\.txt\|version\d\.txt\|sponsor\.txt\|intro\.txt\|tags'
2017-04-19 12:26:01 -07:00
2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/doc/\<\%(' ${ na_doc } '\)\>@norm! d/\v(^diff)|%$
' +w +q " $file "
2016-09-12 04:40:55 -07:00
2017-03-21 03:28:13 -07:00
# Remove "Last change ..." changes in doc files.
2>/dev/null $nvim --cmd 'set dir=/tmp' +'%s/^@@.*\n.*For Vim version.*Last change.*\n.*For Vim version.*Last change.*//' +w +q " $file "
2018-10-05 00:12:52 -07:00
# Remove screen dumps, testdir/Make_*.mak files
local na_src_testdir = 'Make_amiga.mak\|Make_dos.mak\|Make_ming.mak\|Make_vms.mms\|dumps/.*.dump'
2017-04-19 12:26:01 -07:00
2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/testdir/\<\%(' ${ na_src_testdir } '\)\>@norm! d/\v(^diff)|%$
' +w +q " $file "
2016-09-12 04:40:55 -07:00
2017-12-10 16:54:25 -07:00
# Remove version.c #7555
local na_po = 'version.c'
2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/\<\%(' ${ na_po } '\)\>@norm! d/\v(^diff)|%$
' +w +q " $file "
2016-11-17 09:27:13 -07:00
# Remove some *.po files. #5622
local na_po = 'sjiscorr.c\|ja.sjis.po\|ko.po\|pl.cp1250.po\|pl.po\|ru.cp1251.po\|uk.cp1251.po\|zh_CN.cp936.po\|zh_CN.po\|zh_TW.po'
2017-04-19 12:26:01 -07:00
2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/src/po/\<\%(' ${ na_po } '\)\>@norm! d/\v(^diff)|%$
' +w +q " $file "
2017-11-07 12:25:34 -07:00
# Remove vimrc_example.vim
local na_vimrcexample = 'vimrc_example\.vim'
2>/dev/null $nvim --cmd 'set dir=/tmp' +'g@^diff --git a/runtime/\<\%(' ${ na_vimrcexample } '\)\>@norm! d/\v(^diff)|%$
' +w +q " $file "
2016-11-17 09:27:13 -07:00
2016-09-12 04:40:55 -07:00
# Rename src/ paths to src/nvim/
2016-10-19 06:43:04 -07:00
LC_ALL = C sed -e 's/\( [ab]\/src\)/\1\/nvim/g' \
" $file " > " $file " .tmp && mv " $file " .tmp " $file "
# Rename path to matchit plugin.
LC_ALL = C sed -e 's@\( [ab]/runtime\)/pack/dist/opt/matchit/\(plugin/matchit.vim\)@\1/\2@g' \
" $file " > " $file " .tmp && mv " $file " .tmp " $file "
2018-10-13 12:05:07 -07:00
LC_ALL = C sed -e 's@\( [ab]/runtime\)/pack/dist/opt/matchit/doc/\(matchit.txt\)@\1/doc/pi_\2@g' \
" $file " > " $file " .tmp && mv " $file " .tmp " $file "
2018-10-13 09:41:44 -07:00
# Rename test_urls.vim to check_urls.vim
LC_ALL = C sed -e 's@\( [ab]\)/runtime/doc/test\(_urls.vim\)@\1/scripts/check\2@g' \
" $file " > " $file " .tmp && mv " $file " .tmp " $file "
2018-10-13 12:02:57 -07:00
# Rename path to check_colors.vim
LC_ALL = C sed -e 's@\( [ab]/runtime\)/colors/\(tools/check_colors.vim\)@\1/\2@g' \
" $file " > " $file " .tmp && mv " $file " .tmp " $file "
2016-09-12 04:40:55 -07:00
}
2017-12-16 13:38:53 -07:00
get_vimpatch( ) {
2015-07-22 08:00:17 -07:00
get_vim_sources
assign_commit_details " ${ 1 } "
2015-01-07 12:52:10 -07:00
2015-08-25 23:07:31 -07:00
git log -1 " ${ vim_commit } " -- >/dev/null 2>& 1 || {
2018-03-08 04:58:16 -07:00
>& 2 msg_err " Couldn't find Vim revision ' ${ vim_commit } '. "
2015-01-07 12:52:10 -07:00
exit 3
}
2018-03-08 04:58:16 -07:00
msg_ok " Found Vim revision ' ${ vim_commit } '. "
2015-01-07 12:52:10 -07:00
2016-09-12 04:40:55 -07:00
local patch_content
patch_content = " $( git --no-pager show --color= never -1 --pretty= medium " ${ vim_commit } " ) "
2015-01-07 12:52:10 -07:00
2016-09-12 04:40:55 -07:00
cd " ${ NVIM_SOURCE_DIR } "
2016-12-12 18:48:55 -07:00
printf "Creating patch...\n"
echo " $patch_content " > " ${ NVIM_SOURCE_DIR } / ${ patch_file } "
printf "Pre-processing patch...\n"
preprocess_patch " ${ NVIM_SOURCE_DIR } / ${ patch_file } "
2018-08-20 08:41:00 -07:00
msg_ok " Saved patch to ' ${ NVIM_SOURCE_DIR } / ${ patch_file } '. "
2016-12-12 18:48:55 -07:00
}
stage_patch( ) {
2017-12-16 13:38:53 -07:00
get_vimpatch " $1 "
2017-11-06 16:29:19 -07:00
local try_apply = " ${ 2 :- } "
2016-12-12 18:48:55 -07:00
2016-05-11 15:09:39 -07:00
local git_remote
git_remote = " $( find_git_remote) "
local checked_out_branch
checked_out_branch = " $( git rev-parse --abbrev-ref HEAD) "
2016-04-21 18:56:20 -07:00
2016-02-08 16:05:49 -07:00
if [ [ " ${ checked_out_branch } " = = ${ BRANCH_PREFIX } * ] ] ; then
2018-03-08 04:58:16 -07:00
msg_ok " Current branch ' ${ checked_out_branch } ' seems to be a vim-patch "
2016-02-08 16:05:49 -07:00
echo " branch; not creating a new branch."
else
2018-06-19 06:27:32 -07:00
printf '\nFetching "%s/master".\n' " ${ git_remote } "
2016-04-21 18:56:20 -07:00
output = " $( git fetch " ${ git_remote } " master 2>& 1) " &&
2018-03-08 04:58:16 -07:00
msg_ok " ${ output } " ||
( msg_err " ${ output } " ; false )
2016-02-08 16:05:49 -07:00
2016-12-12 18:48:55 -07:00
local nvim_branch = " ${ BRANCH_PREFIX } ${ vim_version } "
2016-02-08 16:05:49 -07:00
echo
2016-09-13 03:18:07 -07:00
echo " Creating new branch ' ${ nvim_branch } ' based on ' ${ git_remote } /master'. "
2016-09-12 04:40:55 -07:00
cd " ${ NVIM_SOURCE_DIR } "
2016-09-13 03:18:07 -07:00
output = " $( git checkout -b " ${ nvim_branch } " " ${ git_remote } /master " 2>& 1) " &&
2018-03-08 04:58:16 -07:00
msg_ok " ${ output } " ||
( msg_err " ${ output } " ; false )
2016-02-08 16:05:49 -07:00
fi
2016-09-13 03:18:07 -07:00
printf "\nCreating empty commit with correct commit message.\n"
2016-02-08 16:05:49 -07:00
output = " $( commit_message | git commit --allow-empty --file 2>& 1 -) " &&
2018-03-08 04:58:16 -07:00
msg_ok " ${ output } " ||
( msg_err " ${ output } " ; false )
2015-01-07 12:52:10 -07:00
2017-11-06 16:29:19 -07:00
if test -n " $try_apply " ; then
if ! check_executable patch; then
2018-03-08 04:58:16 -07:00
printf "\n"
msg_err "'patch' command not found\n"
2017-11-06 16:29:19 -07:00
else
printf "\nApplying patch...\n"
2018-02-01 17:33:34 -07:00
patch -p1 < " ${ patch_file } " || true
2018-08-08 16:56:55 -07:00
find . -name '*.orig' -type f -delete
2017-11-06 16:29:19 -07:00
fi
printf "\nInstructions:\n Proceed to port the patch.\n"
else
2018-06-19 06:27:32 -07:00
printf '\nInstructions:\n Proceed to port the patch.\n Try the "patch" command (or use "%s -P ..." next time):\n patch -p1 < %s\n' " ${ BASENAME } " " ${ patch_file } "
2017-11-06 16:29:19 -07:00
fi
2016-09-13 03:18:07 -07:00
2018-06-19 06:27:32 -07:00
printf '
Stage your changes ( "git add ..." ) , then use "git commit --amend" to commit.
2016-09-13 03:18:07 -07:00
2018-06-19 06:27:32 -07:00
To port more patches ( if any) related to %s,
run "%s" again.
2016-09-13 03:18:07 -07:00
* Do this only for _related_ patches ( otherwise it increases the
size of the pull request, making it harder to review)
2018-06-19 06:27:32 -07:00
When you are done , try "%s -s" to create the pull request.
2016-09-13 03:18:07 -07:00
See the wiki for more information:
2018-06-19 06:27:32 -07:00
* https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-vim
' " ${ vim_version } " " ${ BASENAME } " " ${ BASENAME } "
2015-01-07 12:52:10 -07:00
}
2016-05-16 20:53:56 -07:00
hub_pr( ) {
hub pull-request -m " $1 "
}
git_hub_pr( ) {
git hub pull new -m " $1 "
}
2016-01-23 13:45:21 -07:00
submit_pr( ) {
2016-05-16 20:41:41 -07:00
require_executable git
2016-05-16 20:53:56 -07:00
local push_first
push_first = 1
local submit_fn
if check_executable hub; then
submit_fn = "hub_pr"
elif check_executable git-hub; then
push_first = 0
submit_fn = "git_hub_pr"
else
>& 2 echo " ${ BASENAME } : 'hub' or 'git-hub' not found in PATH or not executable. "
exit 1
fi
2016-01-23 13:45:21 -07:00
2016-09-12 04:40:55 -07:00
cd " ${ NVIM_SOURCE_DIR } "
2016-05-11 15:09:39 -07:00
local checked_out_branch
checked_out_branch = " $( git rev-parse --abbrev-ref HEAD) "
2016-02-08 16:05:49 -07:00
if [ [ " ${ checked_out_branch } " != ${ BRANCH_PREFIX } * ] ] ; then
2018-03-08 04:58:16 -07:00
msg_err " Current branch ' ${ checked_out_branch } ' doesn't seem to be a vim-patch branch. "
2016-01-23 13:45:21 -07:00
exit 1
fi
2016-05-11 15:09:39 -07:00
local git_remote
git_remote = " $( find_git_remote) "
local pr_body
2017-12-16 19:42:08 -07:00
pr_body = " $( git log --grep= vim-patch --reverse --format= '#### %s%n%n%b%n' " ${ git_remote } " /master..HEAD) "
2016-05-11 15:09:39 -07:00
local patches
2017-12-16 19:42:08 -07:00
# Extract just the "vim-patch:X.Y.ZZZZ" or "vim-patch:sha" portion of each log
patches = ( " $( git log --grep= vim-patch --reverse --format= '%s' " ${ git_remote } " /master..HEAD | sed 's/: .*//' ) " )
2016-02-08 16:05:49 -07:00
patches = ( ${ patches [@]//vim-patch : } ) # Remove 'vim-patch:' prefix for each item in array.
2016-05-11 15:09:39 -07:00
local pr_title = " ${ patches [*] } " # Create space-separated string from array.
2016-02-08 16:05:49 -07:00
pr_title = " ${ pr_title // /, } " # Replace spaces with commas.
2016-01-23 13:45:21 -07:00
2016-05-11 15:09:39 -07:00
local pr_message
pr_message = " $( printf '[RFC] vim-patch:%s\n\n%s\n' " ${ pr_title #, } " " ${ pr_body } " ) "
2016-01-23 13:45:21 -07:00
2016-05-16 20:53:56 -07:00
if [ [ $push_first -ne 0 ] ] ; then
echo " Pushing to 'origin/ ${ checked_out_branch } '. "
output = " $( git push origin " ${ checked_out_branch } " 2>& 1) " &&
2018-03-08 04:58:16 -07:00
msg_ok " ${ output } " ||
( msg_err " ${ output } " ; false )
2016-05-16 20:53:56 -07:00
echo
fi
2016-01-23 13:45:21 -07:00
echo "Creating pull request."
2016-05-16 20:53:56 -07:00
output = " $( ${ submit_fn } " ${ pr_message } " 2>& 1) " &&
2018-03-08 04:58:16 -07:00
msg_ok " ${ output } " ||
( msg_err " ${ output } " ; false )
2016-01-23 13:45:21 -07:00
echo
echo "Cleaning up files."
2016-02-08 16:05:49 -07:00
local patch_file
2016-05-11 15:09:39 -07:00
for patch_file in " ${ patches [@] } " ; do
2016-02-08 16:05:49 -07:00
patch_file = " vim- ${ patch_file } .patch "
2016-09-12 04:40:55 -07:00
if [ [ ! -f " ${ NVIM_SOURCE_DIR } / ${ patch_file } " ] ] ; then
2016-02-08 16:05:49 -07:00
continue
fi
2016-09-12 04:40:55 -07:00
rm -- " ${ NVIM_SOURCE_DIR } / ${ patch_file } "
2018-03-08 04:58:16 -07:00
msg_ok " Removed ' ${ NVIM_SOURCE_DIR } / ${ patch_file } '. "
2016-02-08 16:05:49 -07:00
done
2016-01-23 13:45:21 -07:00
}
2017-12-16 13:38:53 -07:00
# Gets all Vim commits since the "start" commit.
list_vim_commits( ) { (
cd " ${ VIM_SOURCE_DIR } " && git log --reverse --format= '%H' v8.0.0000..HEAD
) }
2015-01-07 12:52:10 -07:00
2017-12-25 19:38:42 -07:00
# Prints all (sorted) "vim-patch:xxx" tokens found in the Nvim git log.
2017-12-16 13:38:53 -07:00
list_vimpatch_tokens( ) {
2017-12-04 01:08:07 -07:00
local tokens
2017-12-16 13:38:53 -07:00
# Find all "vim-patch:xxx" tokens in the Nvim git log.
2017-12-04 01:08:07 -07:00
tokens = " $( cd " ${ NVIM_SOURCE_DIR } " && git log -E --grep= 'vim-patch:[^ ]+' | grep 'vim-patch' ) "
2017-12-16 13:38:53 -07:00
echo " $tokens " | grep -E 'vim-patch:[^ ,{]{7,}' \
| sed 's/.*\(vim-patch:[.0-9a-z]\+\).*/\1/' \
| sort \
| uniq
}
2017-12-25 19:38:42 -07:00
# Prints all patch-numbers (for the current v:version) for which there is
# a "vim-patch:xxx" token in the Nvim git log.
list_vimpatch_numbers( ) {
# Transform "vim-patch:X.Y.ZZZZ" to "ZZZZ".
list_vimpatch_tokens | while read vimpatch_token; do
echo " $vimpatch_token " | grep '8\.0\.' | sed 's/.*vim-patch:8\.0\.\([0-9a-z]\+\).*/\1/'
done
}
2017-12-16 13:38:53 -07:00
# Prints a newline-delimited list of Vim commits, for use by scripts.
list_missing_vimpatches( ) {
local tokens vim_commit vim_commits is_missing vim_tag patch_number
# Find all "vim-patch:xxx" tokens in the Nvim git log.
tokens = " $( list_vimpatch_tokens) "
2017-12-04 01:08:07 -07:00
2017-12-16 13:38:53 -07:00
# Get missing Vim commits
vim_commits = " $( list_vim_commits) "
2016-01-19 03:32:14 -07:00
for vim_commit in ${ vim_commits } ; do
2017-12-16 13:38:53 -07:00
# Check for vim-patch:<commit_hash> (usually runtime updates).
is_missing = " $( echo " $tokens " | >/dev/null 2>& 1 grep " vim\-patch: ${ vim_commit : 0 : 7 } " && echo false || echo true ) "
if ! [ " $is_missing " = "false" ] \
&& vim_tag = " $( cd " ${ VIM_SOURCE_DIR } " && git describe --tags --exact-match " ${ vim_commit } " 2>/dev/null) "
then
2017-12-04 01:08:07 -07:00
# Vim version number (not commit hash).
2017-12-16 13:38:53 -07:00
# Check for vim-patch:<tag> (not commit hash).
patch_number = " ${ vim_tag : 1 } " # "v7.4.0001" => "7.4.0001"
2017-12-04 01:08:07 -07:00
is_missing = " $( echo " $tokens " | >/dev/null 2>& 1 grep " vim\-patch: ${ patch_number } " && echo false || echo true ) "
2016-01-19 03:32:14 -07:00
vim_commit = " ${ vim_tag #v } "
2015-01-07 12:52:10 -07:00
fi
2017-12-04 01:08:07 -07:00
if ! [ " $is_missing " = "false" ] ; then
2017-12-10 16:49:44 -07:00
echo " ${ vim_commit } "
fi
done
}
# Prints a human-formatted list of Vim commits, with instructional messages.
2017-12-16 13:38:53 -07:00
show_vimpatches( ) {
2017-12-10 16:49:44 -07:00
get_vim_sources
printf "\nVim patches missing from Neovim:\n"
2017-12-16 13:38:53 -07:00
list_missing_vimpatches | while read vim_commit; do
2017-12-10 16:49:44 -07:00
if ( cd " ${ VIM_SOURCE_DIR } " && git --no-pager show --color= never --name-only " v ${ vim_commit } " 2>/dev/null) | grep -q ^runtime; then
2018-06-19 06:27:32 -07:00
printf ' • %s (+runtime)\n' " ${ vim_commit } "
2017-12-10 16:49:44 -07:00
else
2018-06-19 06:27:32 -07:00
printf ' • %s\n' " ${ vim_commit } "
2015-01-07 12:52:10 -07:00
fi
done
2018-06-19 06:27:32 -07:00
printf " Instructions:
To port one of the above patches to Neovim, execute
this script with the patch revision as argument and
follow the instructions.
Examples: '%s -p 7.4.487'
'%s -p 1e8ebf870720e7b671f98f22d653009826304c4f'
NOTE: Please port the _oldest_ patch if you possibly can.
Out-of-order patches increase the possibility of bugs.
" " ${ BASENAME } " " ${ BASENAME } "
2015-01-07 12:52:10 -07:00
}
2016-01-23 04:05:04 -07:00
review_commit( ) {
2016-09-13 03:18:07 -07:00
local nvim_commit_url = " ${ 1 } "
local nvim_patch_url = " ${ nvim_commit_url } .patch "
2015-07-22 08:00:17 -07:00
local git_patch_prefix = 'Subject: \[PATCH\] '
2016-09-13 03:18:07 -07:00
local nvim_patch
nvim_patch = " $( curl -Ssf " ${ nvim_patch_url } " ) "
2016-05-11 15:09:39 -07:00
local vim_version
2018-07-09 10:55:18 -07:00
vim_version = " $( head -n 4 <<< " ${ nvim_patch } " | sed -n 's/' " ${ git_patch_prefix } " 'vim-patch:\([a-z0-9.]*\)\(:.*\)\{0,1\}$/\1/p' ) "
2015-07-22 08:00:17 -07:00
2016-01-23 04:05:04 -07:00
echo
2015-07-22 08:00:17 -07:00
if [ [ -n " ${ vim_version } " ] ] ; then
2018-03-08 04:58:16 -07:00
msg_ok " Detected Vim patch ' ${ vim_version } '. "
2015-07-22 08:00:17 -07:00
else
2018-03-08 04:58:16 -07:00
msg_err "Could not detect the Vim patch number."
2016-02-08 16:05:49 -07:00
echo " This script assumes that the PR contains only commits"
echo " with 'vim-patch:XXX' in their title."
2016-12-15 07:09:52 -07:00
echo
2018-06-19 06:27:32 -07:00
printf -- '%s\n\n' " $( head -n 4 <<< " ${ nvim_patch } " ) "
2016-12-15 07:09:52 -07:00
local reply
read -p "Continue reviewing (y/N)? " -n 1 -r reply
2016-12-21 19:17:01 -07:00
if [ [ " ${ reply } " = = y ] ] ; then
2016-12-15 07:09:52 -07:00
echo
return
fi
2015-07-22 08:00:17 -07:00
exit 1
fi
assign_commit_details " ${ vim_version } "
2018-07-10 16:54:44 -07:00
echo
echo "Creating files."
echo " ${ nvim_patch } " > " ${ NVIM_SOURCE_DIR } /n ${ patch_file } "
msg_ok " Saved pull request diff to ' ${ NVIM_SOURCE_DIR } /n ${ patch_file } '. "
CREATED_FILES += ( " ${ NVIM_SOURCE_DIR } /n ${ patch_file } " )
local nvim = "nvim -u NORC -n -i NONE --headless"
2>/dev/null $nvim --cmd 'set dir=/tmp' +'1,/^$/g/^ /-1join' +w +q " ${ NVIM_SOURCE_DIR } /n ${ patch_file } "
2016-05-11 15:09:39 -07:00
local expected_commit_message
expected_commit_message = " $( commit_message) "
local message_length
message_length = " $( wc -l <<< " ${ expected_commit_message } " ) "
local commit_message
2018-07-10 16:54:44 -07:00
commit_message = " $( tail -n +4 " ${ NVIM_SOURCE_DIR } /n ${ patch_file } " | head -n " ${ message_length } " ) "
2015-07-22 08:00:17 -07:00
if [ [ " ${ commit_message # ${ git_patch_prefix } } " = = " ${ expected_commit_message } " ] ] ; then
2018-03-08 04:58:16 -07:00
msg_ok "Found expected commit message."
2015-07-22 08:00:17 -07:00
else
2018-03-08 04:58:16 -07:00
msg_err "Wrong commit message."
2015-07-22 08:00:17 -07:00
echo " Expected:"
echo " ${ expected_commit_message } "
echo " Actual:"
echo " ${ commit_message # ${ git_patch_prefix } } "
fi
2017-12-16 13:38:53 -07:00
get_vimpatch " ${ vim_version } "
2016-09-12 04:40:55 -07:00
CREATED_FILES += ( " ${ NVIM_SOURCE_DIR } / ${ patch_file } " )
2015-07-22 08:00:17 -07:00
echo
echo "Launching nvim."
2016-09-12 04:40:55 -07:00
nvim -c " cd ${ NVIM_SOURCE_DIR } " \
-O " ${ NVIM_SOURCE_DIR } / ${ patch_file } " " ${ NVIM_SOURCE_DIR } /n ${ patch_file } "
2016-01-23 04:05:04 -07:00
}
review_pr( ) {
2016-05-16 20:41:41 -07:00
require_executable curl
require_executable nvim
require_executable jq
2016-01-23 04:05:04 -07:00
get_vim_sources
local pr = " ${ 1 } "
echo
echo " Downloading data for pull request # ${ pr } . "
local pr_commit_urls = ( $( curl -Ssf " https://api.github.com/repos/neovim/neovim/pulls/ ${ pr } /commits " \
| jq -r '.[].html_url' ) )
echo " Found ${# pr_commit_urls [@] } commit(s). "
local pr_commit_url
local reply
2016-05-11 15:09:39 -07:00
for pr_commit_url in " ${ pr_commit_urls [@] } " ; do
2016-01-23 13:45:21 -07:00
review_commit " ${ pr_commit_url } "
2016-01-23 04:05:04 -07:00
if [ [ " ${ pr_commit_url } " != " ${ pr_commit_urls [-1] } " ] ] ; then
read -p "Continue with next commit (Y/n)? " -n 1 -r reply
echo
2016-12-21 19:17:01 -07:00
if [ [ " ${ reply } " = = n ] ] ; then
2016-01-23 04:05:04 -07:00
break
fi
fi
done
clean_files
2015-07-22 08:00:17 -07:00
}
2017-12-25 19:38:42 -07:00
while getopts "hlLMVp:P:g:r:s" opt; do
2015-07-22 08:00:17 -07:00
case ${ opt } in
h)
usage
exit 0
; ;
l)
2017-12-16 13:38:53 -07:00
show_vimpatches
2017-12-10 16:49:44 -07:00
exit 0
; ;
L)
2017-12-16 13:38:53 -07:00
list_missing_vimpatches
2015-07-22 08:00:17 -07:00
exit 0
; ;
2017-12-25 19:38:42 -07:00
M)
list_vimpatch_numbers
exit 0
; ;
2015-07-22 08:00:17 -07:00
p)
2016-12-12 18:48:55 -07:00
stage_patch " ${ OPTARG } "
exit 0
; ;
2017-11-06 16:29:19 -07:00
P)
stage_patch " ${ OPTARG } " TRY_APPLY
exit 0
; ;
2016-12-12 18:48:55 -07:00
g)
2017-12-16 13:38:53 -07:00
get_vimpatch " ${ OPTARG } "
2015-07-22 08:00:17 -07:00
exit 0
; ;
r)
review_pr " ${ OPTARG } "
exit 0
; ;
2016-01-23 13:45:21 -07:00
s)
submit_pr
exit 0
; ;
2017-12-10 17:58:55 -07:00
V)
get_vim_sources
exit 0
; ;
2015-07-22 08:00:17 -07:00
*)
exit 1
; ;
esac
done
usage
# vim: et sw=2