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