tzdata2netbsd revision 1.11 1 1.11 kre # $NetBSD: tzdata2netbsd,v 1.11 2016/11/03 10:11:05 kre Exp $
2 1.1 apb
3 1.1 apb # For use by NetBSD developers when updating to new versions of tzdata.
4 1.1 apb #
5 1.2 apb # 0. Be in an up-to-date checkout of src/external/public-domain/tz
6 1.2 apb # from NetBSD-current.
7 1.1 apb # 1. Edit OLDVER and NEWVER below.
8 1.9 agc # 2. Make sure that you have Paul Eggert's 4K RSA public key in your
9 1.9 agc # keyring (62AA7E34, eggert (a] cs.ucla.edu)
10 1.9 agc # 3. Run this script. You will be prompted for confirmation before
11 1.1 apb # anything major (such as a cvs operation).
12 1.9 agc # 4. If something fails, abort the script and fix it.
13 1.9 agc # 5. Re-run this script until you are happy. It's designed to
14 1.1 apb # be re-run over and over, and later runs will try not to
15 1.1 apb # redo non-trivial work done by earlier runs.
16 1.1 apb #
17 1.1 apb
18 1.11 kre OLDVER=2016h
19 1.11 kre NEWVER=2016i
20 1.1 apb
21 1.1 apb # Uppercase variants of OLDVER and NEWVER
22 1.1 apb OLDVER_UC="$( echo "${OLDVER}" | tr '[a-z]' '[A-Z]' )"
23 1.1 apb NEWVER_UC="$( echo "${NEWVER}" | tr '[a-z]' '[A-Z]' )"
24 1.1 apb
25 1.1 apb # Tags for use with version control systems
26 1.1 apb CVSOLDTAG="TZDATA${OLDVER_UC}"
27 1.1 apb CVSNEWTAG="TZDATA${NEWVER_UC}"
28 1.1 apb CVSBRANCHTAG="TZDATA"
29 1.1 apb GITHUBTAG="${NEWVER}"
30 1.1 apb
31 1.1 apb # URLs for fetching distribution files, etc.
32 1.1 apb DISTURL="ftp://ftp.iana.org/tz/releases/tzdata${NEWVER}.tar.gz"
33 1.1 apb SIGURL="${DISTURL}.asc"
34 1.1 apb NEWSURL="https://github.com/eggert/tz/raw/${GITHUBTAG}/NEWS"
35 1.1 apb
36 1.1 apb # Directories
37 1.2 apb REPODIR="src/external/public-domain/tz/dist" # relative to the NetBSD CVS repo
38 1.3 apb TZDISTDIR="$(pwd)/dist" # should be .../external/public-domain/tz/dist
39 1.1 apb WORKDIR="$(pwd)/update-work/${NEWVER}"
40 1.1 apb EXTRACTDIR="${WORKDIR}/extract"
41 1.1 apb
42 1.1 apb # Files in the work directory
43 1.1 apb DISTFILE="${WORKDIR}/${DISTURL##*/}"
44 1.1 apb SIGFILE="${DISTFILE}.sig"
45 1.5 apb PGPVERIFYLOG="${WORKDIR}/pgpverify.log"
46 1.1 apb NEWSFILE="${WORKDIR}/NEWS"
47 1.1 apb NEWSTRIMFILE="${WORKDIR}/NEWS.trimmed"
48 1.1 apb IMPORTMSGFILE="${WORKDIR}/import.msg"
49 1.5 apb IMPORTDONEFILE="${WORKDIR}/import.done"
50 1.1 apb MERGSMSGFILE="${WORKDIR}/merge.msg"
51 1.5 apb MERGEDONEFILE="${WORKDIR}/merge.done"
52 1.5 apb COMMITMERGEDONEFILE="${WORKDIR}/commitmerge.done"
53 1.1 apb
54 1.9 agc EDITOR=${EDITOR:-vi}
55 1.9 agc
56 1.1 apb DOIT()
57 1.1 apb {
58 1.1 apb local really_do_it=false
59 1.1 apb local reply
60 1.1 apb
61 1.3 apb echo "In directory $(pwd)"
62 1.1 apb echo "ABOUT TO DO:" "$(shell_quote "$@")"
63 1.1 apb read -p "Really do it? [yes/no/quit] " reply
64 1.1 apb case "${reply}" in
65 1.1 apb [yY]*) really_do_it=true ;;
66 1.1 apb [nN]*) really_do_it=false ;;
67 1.1 apb [qQ]*)
68 1.1 apb echo "Aborting"
69 1.1 apb return 1
70 1.1 apb ;;
71 1.1 apb esac
72 1.1 apb if $really_do_it; then
73 1.1 apb echo "REALLY DOING IT NOW..."
74 1.1 apb "$@"
75 1.1 apb else
76 1.1 apb echo "NOT REALLY DOING THE ABOVE COMMAND"
77 1.1 apb fi
78 1.1 apb }
79 1.1 apb
80 1.1 apb # Quote args to make them safe in the shell.
81 1.1 apb # Usage: quotedlist="$(shell_quote args...)"
82 1.1 apb #
83 1.1 apb # After building up a quoted list, use it by evaling it inside
84 1.1 apb # double quotes, like this:
85 1.1 apb # eval "set -- $quotedlist"
86 1.1 apb # or like this:
87 1.1 apb # eval "\$command $quotedlist \$filename"
88 1.1 apb #
89 1.1 apb shell_quote()
90 1.1 apb {(
91 1.1 apb local result=''
92 1.1 apb local arg qarg
93 1.1 apb LC_COLLATE=C ; export LC_COLLATE # so [a-zA-Z0-9] works in ASCII
94 1.1 apb for arg in "$@" ; do
95 1.1 apb case "${arg}" in
96 1.1 apb '')
97 1.1 apb qarg="''"
98 1.1 apb ;;
99 1.1 apb *[!-./a-zA-Z0-9]*)
100 1.1 apb # Convert each embedded ' to '\'',
101 1.1 apb # then insert ' at the beginning of the first line,
102 1.1 apb # and append ' at the end of the last line.
103 1.1 apb # Finally, elide unnecessary '' pairs at the
104 1.1 apb # beginning and end of the result and as part of
105 1.1 apb # '\'''\'' sequences that result from multiple
106 1.1 apb # adjacent quotes in he input.
107 1.1 apb qarg="$(printf "%s\n" "$arg" | \
108 1.1 apb ${SED:-sed} -e "s/'/'\\\\''/g" \
109 1.1 apb -e "1s/^/'/" -e "\$s/\$/'/" \
110 1.1 apb -e "1s/^''//" -e "\$s/''\$//" \
111 1.1 apb -e "s/'''/'/g"
112 1.1 apb )"
113 1.1 apb ;;
114 1.1 apb *)
115 1.1 apb # Arg is not the empty string, and does not contain
116 1.1 apb # any unsafe characters. Leave it unchanged for
117 1.1 apb # readability.
118 1.1 apb qarg="${arg}"
119 1.1 apb ;;
120 1.1 apb esac
121 1.1 apb result="${result}${result:+ }${qarg}"
122 1.1 apb done
123 1.1 apb printf "%s\n" "$result"
124 1.1 apb )}
125 1.1 apb
126 1.1 apb findcvsroot()
127 1.1 apb {
128 1.1 apb [ -n "${CVSROOT}" ] && return 0
129 1.1 apb CVSROOT="$( cat ./CVS/Root )"
130 1.1 apb [ -n "${CVSROOT}" ] && return 0
131 1.1 apb echo >&2 "Failed to set CVSROOT value"
132 1.1 apb return 1
133 1.1 apb }
134 1.1 apb
135 1.1 apb mkworkdir()
136 1.1 apb {
137 1.1 apb mkdir -p "${WORKDIR}"
138 1.1 apb }
139 1.1 apb
140 1.1 apb fetch()
141 1.1 apb {
142 1.1 apb [ -f "${DISTFILE}" ] || ftp -o "${DISTFILE}" "${DISTURL}"
143 1.1 apb [ -f "${SIGFILE}" ] || ftp -o "${SIGFILE}" "${SIGURL}"
144 1.1 apb [ -f "${NEWSFILE}" ] || ftp -o "${NEWSFILE}" "${NEWSURL}"
145 1.1 apb }
146 1.1 apb
147 1.1 apb checksig()
148 1.1 apb {
149 1.1 apb { gpg --verify "${SIGFILE}" "${DISTFILE}"
150 1.1 apb echo gpg exit status $?
151 1.1 apb } 2>&1 | tee "${PGPVERIFYLOG}"
152 1.1 apb
153 1.1 apb # The output should contain lines that match all the following regexps
154 1.1 apb #
155 1.1 apb while read line; do
156 1.11 kre if ! grep -E -q -e "^${line}\$" "${PGPVERIFYLOG}"; then
157 1.1 apb echo >&2 "Failed to verify signature: ${line}"
158 1.1 apb return 1
159 1.1 apb fi
160 1.1 apb done <<'EOF'
161 1.11 kre gpg: Signature made .* using RSA key ID (62AA7E34|44AD418C)
162 1.1 apb gpg: Good signature from "Paul Eggert <eggert (a] cs.ucla.edu>"
163 1.1 apb gpg exit status 0
164 1.1 apb EOF
165 1.1 apb }
166 1.1 apb
167 1.1 apb extract()
168 1.1 apb {
169 1.1 apb [ -f "${EXTRACTDIR}/zone.tab" ] && return
170 1.1 apb mkdir -p "${EXTRACTDIR}"
171 1.1 apb tar -z -xf "${DISTFILE}" -C "${EXTRACTDIR}"
172 1.1 apb }
173 1.1 apb
174 1.2 apb addnews()
175 1.2 apb {
176 1.2 apb [ -f "${EXTRACTDIR}/NEWS" ] && return
177 1.2 apb cp -p "${NEWSFILE}" "${EXTRACTDIR}"/NEWS
178 1.2 apb }
179 1.2 apb
180 1.1 apb # Find the relevant part of the NEWS file for all releases between
181 1.1 apb # OLDVER and NEWVER, and save them to NEWSTRIMFILE.
182 1.1 apb #
183 1.1 apb trimnews()
184 1.1 apb {
185 1.1 apb [ -s "${NEWSTRIMFILE}" ] && return
186 1.1 apb awk -v oldver="${OLDVER}" -v newver="${NEWVER}" \
187 1.1 apb '
188 1.1 apb BEGIN {inrange = 0}
189 1.1 apb /^Release [0-9]+[a-z]+ - .*/ {
190 1.1 apb # "Release <version> - <date>"
191 1.1 apb inrange = ($2 > oldver && $2 <= newver)
192 1.1 apb }
193 1.1 apb // { if (inrange) print; }
194 1.1 apb ' \
195 1.1 apb <"${NEWSFILE}" >"${NEWSTRIMFILE}"
196 1.10 agc echo "tzdata-${NEWVER}" > ${TZDISTDIR}/TZDATA_VERSION
197 1.1 apb }
198 1.1 apb
199 1.1 apb # Create IMPORTMSGFILE from NEWSTRIMFILE, by ignoring some sections,
200 1.1 apb # keeping only the first sentence from paragraphs in other sections,
201 1.1 apb # and changing the format.
202 1.1 apb #
203 1.1 apb # The result should be edited by hand before performing a cvs commit.
204 1.1 apb # A message to that effect is inserted at the beginning of the file.
205 1.1 apb #
206 1.1 apb mkimportmsg()
207 1.1 apb {
208 1.1 apb [ -s "${IMPORTMSGFILE}" ] && return
209 1.1 apb { cat <<EOF
210 1.1 apb EDIT ME: Edit this file and then delete the lines marked "EDIT ME".
211 1.1 apb EDIT ME: This file will be used as a log message for the "cvs commit" that
212 1.1 apb EDIT ME: imports tzdata${NEWVER}. The initial contents of this file were
213 1.1 apb EDIT ME: generated from ${NEWSFILE}.
214 1.1 apb EDIT ME:
215 1.1 apb EOF
216 1.1 apb awk -v oldver="${OLDVER}" -v newver="${NEWVER}" \
217 1.2 apb -v disturl="${DISTURL}" -v newsurl="${NEWSURL}" \
218 1.1 apb '
219 1.1 apb BEGIN {
220 1.1 apb bullet = " * ";
221 1.1 apb indent = " ";
222 1.1 apb blankline = 0;
223 1.1 apb goodsection = 0;
224 1.1 apb havesentence = 0;
225 1.1 apb print "Import tzdata"newver" from "disturl;
226 1.4 apb #print "and NEWS file from "newsurl;
227 1.1 apb }
228 1.1 apb /^Release/ {
229 1.1 apb # "Release <version> - <date>"
230 1.1 apb ver = $2;
231 1.1 apb date = gensub(".* - ", "", 1, $0);
232 1.1 apb print "";
233 1.1 apb print "Summary of changes in tzdata"ver \
234 1.1 apb " ("date"):";
235 1.1 apb }
236 1.1 apb /^$/ { blankline = 1; havesentence = 0; }
237 1.1 apb /^ Changes affecting/ { goodsection = 0; }
238 1.1 apb /^ Changes affecting.*time/ { goodsection = 1; }
239 1.7 apb /^ Changes affecting.*data/ { goodsection = 1; }
240 1.1 apb /^ Changes affecting.*documentation/ || \
241 1.1 apb /^ Changes affecting.*commentary/ {
242 1.1 apb t = gensub("^ *", "", 1, $0);
243 1.1 apb t = gensub("\\.*$", ".", 1, t);
244 1.1 apb print bullet t;
245 1.1 apb goodsection = 0;
246 1.1 apb }
247 1.1 apb /^ .*/ && goodsection {
248 1.1 apb # In a paragraph in a "good" section.
249 1.1 apb # Ignore leading spaces, and ignore anything
250 1.1 apb # after the first sentence.
251 1.1 apb # First line of paragraph gets a bullet.
252 1.1 apb t = gensub("^ *", "", 1, $0);
253 1.1 apb t = gensub("\\. .*", ".", 1, t);
254 1.1 apb if (blankline) print bullet t;
255 1.1 apb else if (! havesentence) print indent t;
256 1.1 apb havesentence = (havesentence || (t ~ "\\.$"));
257 1.1 apb }
258 1.1 apb /./ { blankline = 0; }
259 1.1 apb ' \
260 1.1 apb <"${NEWSTRIMFILE}"
261 1.1 apb } >"${IMPORTMSGFILE}"
262 1.1 apb }
263 1.1 apb
264 1.1 apb editimportmsg()
265 1.1 apb {
266 1.1 apb if [ -s "${IMPORTMSGFILE}" ] \
267 1.1 apb && ! grep -q '^EDIT' "${IMPORTMSGFILE}"
268 1.1 apb then
269 1.1 apb return 0 # file has already been edited
270 1.1 apb fi
271 1.1 apb # Pass both IMPORTMSGFILE and NEWSFILE to the editor, so that the
272 1.1 apb # user can easily consult NEWSFILE while editing IMPORTMSGFILE.
273 1.9 agc ${EDITOR} "${IMPORTMSGFILE}" "${NEWSFILE}"
274 1.1 apb }
275 1.1 apb
276 1.1 apb cvsimport()
277 1.1 apb {
278 1.6 apb if [ -e "${IMPORTDONEFILE}" ]; then
279 1.5 apb cat >&2 <<EOF
280 1.5 apb The CVS import has already been performed.
281 1.5 apb EOF
282 1.5 apb return 0
283 1.5 apb fi
284 1.1 apb if ! [ -s "${IMPORTMSGFILE}" ] \
285 1.1 apb || grep -q '^EDIT' "${IMPORTMSGFILE}"
286 1.1 apb then
287 1.1 apb cat >&2 <<EOF
288 1.1 apb The message file ${IMPORTMSGFILE}
289 1.1 apb has not been properly edited.
290 1.1 apb Not performing cvs import.
291 1.1 apb EOF
292 1.1 apb return 1
293 1.1 apb fi
294 1.1 apb ( cd "${EXTRACTDIR}" &&
295 1.1 apb DOIT cvs -d "${CVSROOT}" import -m "$(cat "${IMPORTMSGFILE}")" \
296 1.1 apb "${REPODIR}" "${CVSBRANCHTAG}" "${CVSNEWTAG}"
297 1.6 apb ) && touch "${IMPORTDONEFILE}"
298 1.1 apb }
299 1.1 apb
300 1.1 apb cvsmerge()
301 1.5 apb {
302 1.3 apb
303 1.3 apb cd "${TZDISTDIR}" || exit 1
304 1.6 apb if [ -e "${MERGEDONEFILE}" ]; then
305 1.5 apb cat >&2 <<EOF
306 1.5 apb The CVS merge has already been performed.
307 1.5 apb EOF
308 1.5 apb return 0
309 1.5 apb fi
310 1.6 apb DOIT cvs -d "${CVSROOT}" update -j"${CVSOLDTAG}" -j"${CVSNEWTAG}" \
311 1.6 apb && touch "${MERGEDONEFILE}"
312 1.5 apb }
313 1.1 apb
314 1.1 apb resolveconflicts()
315 1.1 apb {
316 1.5 apb cd "${TZDISTDIR}" || exit 1
317 1.5 apb if grep -l '^[<=>][<=>][<=>]' *
318 1.5 apb then
319 1.5 apb cat <<EOF
320 1.5 apb There appear to be conflicts in the files listed above.
321 1.5 apb Resolve conflicts, then re-run this script.
322 1.1 apb EOF
323 1.5 apb return 1
324 1.5 apb fi
325 1.1 apb }
326 1.1 apb
327 1.1 apb cvscommitmerge()
328 1.5 apb {
329 1.3 apb cd "${TZDISTDIR}" || exit 1
330 1.1 apb if grep -l '^[<=>][<=>][<=>]' *
331 1.1 apb then
332 1.1 apb cat >&2 <<EOF
333 1.1 apb There still appear to be conflicts in the files listed above.
334 1.1 apb Not performing cvs commit.
335 1.1 apb EOF
336 1.1 apb return 1
337 1.1 apb fi
338 1.6 apb if [ -e "${COMMITMERGEDONEFILE}" ]; then
339 1.5 apb cat >&2 <<EOF
340 1.5 apb The CVS commmit (of the merge result) has already been performed.
341 1.5 apb EOF
342 1.5 apb return 0
343 1.5 apb fi
344 1.6 apb DOIT cvs -d "${CVSROOT}" commit -m "Merge tzdata${NEWVER}" \
345 1.6 apb && touch "${COMMITMERGEDONEFILE}"
346 1.5 apb }
347 1.1 apb
348 1.1 apb extra()
349 1.1 apb {
350 1.1 apb cat <<EOF
351 1.1 apb Also do the following:
352 1.1 apb * Edit src/doc/3RDPARTY
353 1.1 apb * Edit src/doc/CHANGES
354 1.11 kre * Edit src/distrib/sets/lists/base/mi if the set of installed files altered.
355 1.1 apb * Submit pullup requests for all active release branches.
356 1.1 apb * rm -rf ${WORKDIR}
357 1.1 apb EOF
358 1.1 apb }
359 1.1 apb
360 1.1 apb main()
361 1.1 apb {
362 1.1 apb set -e
363 1.1 apb findcvsroot
364 1.1 apb mkworkdir
365 1.1 apb fetch
366 1.1 apb checksig
367 1.1 apb extract
368 1.2 apb addnews
369 1.1 apb trimnews
370 1.1 apb mkimportmsg
371 1.1 apb editimportmsg
372 1.1 apb cvsimport
373 1.1 apb cvsmerge
374 1.1 apb resolveconflicts
375 1.1 apb cvscommitmerge
376 1.1 apb extra
377 1.1 apb }
378 1.1 apb
379 1.1 apb main "$@"
380