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