1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
#!/usr/bin/env bash
set -e
set -o pipefail
readonly NEOVIM_SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
readonly VIM_SOURCE_DIR_DEFAULT=${NEOVIM_SOURCE_DIR}/.vim-src
readonly VIM_SOURCE_DIR="${VIM_SOURCE_DIR:-${VIM_SOURCE_DIR_DEFAULT}}"
readonly BASENAME="$(basename "${0}")"
usage() {
echo "Helper script for porting Vim patches. For more information, see"
echo "https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-vim"
echo
echo "Usage: ${BASENAME} [option]"
echo " ${BASENAME} vim-revision"
echo
echo "Options:"
echo " -h, --help Show this message."
echo " -l, --list Show list of Vim patches missing from Neovim."
echo
echo "vim-revision can be a version number of the format '7.4.xxx'"
echo "or a Mercurial commit hash."
echo
echo "Set VIM_SOURCE_DIR to change where Vim's sources are stored."
echo "The default is '${VIM_SOURCE_DIR_DEFAULT}'."
}
get_vim_sources() {
echo "Retrieving Vim sources."
if [[ ! -d ${VIM_SOURCE_DIR} ]]; then
echo "Cloning Vim sources into '${VIM_SOURCE_DIR}'."
hg clone https://code.google.com/p/vim "${VIM_SOURCE_DIR}"
cd "${VIM_SOURCE_DIR}"
else
echo "Updating Vim sources in '${VIM_SOURCE_DIR}'."
cd "${VIM_SOURCE_DIR}"
hg pull --update &&
echo "✔ Updated Vim sources." ||
echo "✘ Could not update Vim sources; ignoring error."
fi
}
get_vim_patch() {
if [[ ${1} =~ [0-9]\.[0-9]\.[0-9]{3,4} ]]; then
# Interpret parameter as version number.
vim_version="${1}"
vim_commit="v${1//./-}"
strip_commit_line=true
vim_commit_url="https://github.com/vim/vim/commit/${vim_commit}"
else
# Interpret parameter as commit hash.
vim_version="${1:0:7}"
vim_commit="${1}"
strip_commit_line=false
vim_commit_url="https://code.google.com/p/vim/source/detail?r=${vim_commit}"
fi
hg log --rev "${vim_commit}" >/dev/null 2>&1 || {
>&2 echo "✘ Couldn't find Vim revision '${vim_commit}'."
exit 3
}
echo
echo "✔ Found Vim revision '${vim_commit}'."
# Collect patch details and store into variables.
vim_full="$(hg log --patch --git --verbose --rev "${vim_commit}")"
vim_message="$(hg log --template "{desc}" --rev "${vim_commit}")"
if [[ ${strip_commit_line} == "true" ]]; then
# Remove first line of commit message.
vim_message="$(echo "${vim_message}" | sed -e '1d')"
fi
vim_diff="$(hg diff --show-function --git --change "${vim_commit}" \
| sed -e 's/\( [ab]\/src\)/\1\/nvim/g')" # Change directory to src/nvim.
neovim_message="
vim-patch:${vim_version}
${vim_message}
${vim_commit_url}"
neovim_pr="
\`\`\`
${vim_message}
\`\`\`
${vim_commit_url}
Original patch:
\`\`\`diff
${vim_diff}
\`\`\`"
neovim_branch="vim-${vim_version}"
echo
echo "Creating Git branch."
cd "${NEOVIM_SOURCE_DIR}"
output="$(git checkout -b "${neovim_branch}" 2>&1)" &&
echo "✔ ${output}" ||
(echo "✘ ${output}"; false)
echo
echo "Creating empty commit with correct commit message."
output="$(git commit --allow-empty --file 2>&1 - <<< "${neovim_message}")" &&
echo "✔ ${output}" ||
(echo "✘ ${output}"; false)
echo
echo "Creating files."
echo "${vim_diff}" > "${NEOVIM_SOURCE_DIR}/${neovim_branch}.diff"
echo "✔ Saved patch to '${NEOVIM_SOURCE_DIR}/${neovim_branch}.diff'."
echo "${vim_full}" > "${NEOVIM_SOURCE_DIR}/${neovim_branch}.patch"
echo "✔ Saved full commit details to '${NEOVIM_SOURCE_DIR}/${neovim_branch}.patch'."
echo "${neovim_pr}" > "${NEOVIM_SOURCE_DIR}/${neovim_branch}.pr"
echo "✔ Saved suggested PR description to '${NEOVIM_SOURCE_DIR}/${neovim_branch}.pr'."
echo "You can use 'git clean' to remove these files when you're done."
echo
echo "Instructions:"
echo
echo " Proceed to port the patch."
echo " You might want to try 'patch -p1 < ${neovim_branch}.diff' first."
echo
echo " Stage your changes ('git add ...') and use 'git commit --amend' to commit."
echo
echo " Push your changes with 'git push origin ${neovim_branch}' and create a"
echo " pull request called '[RFC] vim-patch:${vim_version}'. You might want "
echo " to use the text in '${neovim_branch}.pr' as the description of this pull request."
echo
echo " See https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-vim"
echo " for more information."
}
list_vim_patches() {
echo
echo "Vim patches missing from Neovim:"
# Get vim patches and runtime file updates.
# Start from 7.4.442. The runtime was re-integrated from 7.4.384, but
# runtime patches before between 384 and 442 have already been ported
# to Neovim as of the creation of this script.
local vim_commits=$(cd "${VIM_SOURCE_DIR}" && \
hg log --removed --template='{if(startswith("Added tag", firstline(desc)),
"{latesttag}\n",
"{if(startswith(\"updated for version\", firstline(desc)),
\"\",
\"{node}\n\")}")}' -r tip:v7-4-442)
# Append remaining vim patches.
# Start from 7.4.160, where Neovim was forked.
local vim_old_commits=$(cd "${VIM_SOURCE_DIR}" && \
hg log --removed --template='{if(startswith("Added tag",
firstline(desc)),
"{latesttag}\n")}' -r v7-4-442:v7-4-161)
local vim_commit
for vim_commit in ${vim_commits} ${vim_old_commits}; do
local is_missing
if [[ ${vim_commit} =~ v([0-9]-[0-9]-([0-9]{3,4})) ]]; then
local patch_number="${BASH_REMATCH[2]}"
# "Proper" Vim patch
# Check version.c:
is_missing="$(sed -n '/static int included_patches/,/}/p' "${NEOVIM_SOURCE_DIR}/src/nvim/version.c" |
grep -x -e "[[:space:]]*//${patch_number} NA" -e "[[:space:]]*${patch_number}," >/dev/null && echo "false" || echo "true")"
vim_commit="${BASH_REMATCH[1]//-/.}"
else
# Untagged Vim patch, e.g. runtime updates.
# Check Neovim log:
is_missing="$(cd "${NEOVIM_SOURCE_DIR}" &&
git log -1 --no-merges --grep="vim\-patch:${vim_commit:0:7}" --pretty=format:"false")"
fi
if [[ ${is_missing} != "false" ]]; then
echo " • ${vim_commit}"
fi
done
echo
echo "Instructions:"
echo
echo " To port one of the above patches to Neovim, execute"
echo " this script with the patch revision as argument."
echo
echo " Examples: '${BASENAME} 7.4.487'"
echo " '${BASENAME} 1e8ebf870720e7b671f98f22d653009826304c4f'"
}
if [[ ${1} == "--help" || ${1} == "-h" ]]; then
usage
exit 0
elif [[ ${#} != 1 ]]; then
usage
exit 1
fi
# Checks if mercurial is in the user's PATH, and is executable.
if [[ ! -x $(command -v hg) ]]; then
>&2 echo "${BASENAME}: 'hg' (mercurial) not found in PATH or not executable"
exit 1
fi
get_vim_sources
if [[ ${1} == "--list" || ${1} == "-l" ]]; then
list_vim_patches
else
get_vim_patch "${1}"
fi
|