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