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