tzdata2netbsd revision 1.17 1 1.17 kre # $NetBSD: tzdata2netbsd,v 1.17 2025/12/19 01:17:21 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.12 kre # 1. Make sure that you have Paul Eggert's 4K RSA public key in your
8 1.12 kre # keyring (62AA7E34, eggert (a] cs.ucla.edu) It is not required that it be trusted.
9 1.12 kre # 2. Run this script. You will be prompted for confirmation before
10 1.12 kre # anything major (such as a cvs operation). The tz versions can be
11 1.12 kre # specified as args (new version first, and the previous second) if
12 1.12 kre # needed to override the calculated values
13 1.12 kre # 3. If something fails, abort the script and fix it.
14 1.12 kre # 4. Re-run this script until you are happy. It's designed to
15 1.1 apb # be re-run over and over, and later runs will try not to
16 1.1 apb # redo non-trivial work done by earlier runs.
17 1.1 apb #
18 1.1 apb
19 1.12 kre VERS_PATTERN='2[0-9][0-9][0-9][a-z]'
20 1.12 kre # This needs to be updated twice every millennium to allow for the
21 1.12 kre # new millenium's years.
22 1.12 kre # First in the late xx90's sometime, allow the new one by changing the leading
23 1.12 kre # digit from a specific value to the class containing the current and
24 1.12 kre # following values (eg: in 2098 or so, change '2' to be '[23]').
25 1.16 kre # Then in the following early xx00's sometime, delete the class, and
26 1.12 kre # leave only the current value as valid (eg: in 3001 or 3002,
27 1.12 kre # change '[23]' to be just '3'
28 1.12 kre # Doing it this way helps guard against invalid specifications.
29 1.12 kre # We could automate this, but it is (IMO) not worth the cost, to avoid a
30 1.12 kre # twice a millenium edit requirement.
31 1.12 kre # A more significant (and harder) change will be needed in the late 9990's
32 1.12 kre # If this script lasts until then, send me a postcard, I'll be waiting for it!
33 1.12 kre # Things get easier again after that until the late 99990's (etc.)
34 1.12 kre
35 1.12 kre # Note the pattern is used on both the old and new version specifiers,
36 1.12 kre # so it must be able to cope with the shift from one form (eg 2999g)
37 1.12 kre # to the new one (eg: 3000a) without failing (or the code that uses it
38 1.12 kre # below needs to be updated).
39 1.12 kre
40 1.12 kre # Also note that the option of having a second alpha (1997aa or something)
41 1.12 kre # to handle years with much activity is handled below, the pattern does not
42 1.12 kre # need to match those.
43 1.12 kre # If that convention changes (as of date of writing, it has never been
44 1.12 kre # exercised) then code changes below will be required.
45 1.16 kre # Note it doesn't matter (here) if nnnnz is followed by nnnnaa or nnnnza
46 1.12 kre
47 1.12 kre DIST_HOST=ftp.iana.org
48 1.12 kre DIST_PATH=tz
49 1.12 kre DIST_FILES=releases
50 1.1 apb
51 1.16 kre GTZURL=https://github.com/JodaOrg/global-tz/releases/download
52 1.16 kre
53 1.12 kre EDITOR=${EDITOR:-vi}
54 1.16 kre
55 1.16 kre TZBASE=$(pwd) || fail 'Cannot find myself ($PWD)'
56 1.16 kre cd -P "$TZBASE" || fail "Cannot return home: ${TZBASE}"
57 1.16 kre
58 1.16 kre WORK_PFX=${TZBASE}/update-work
59 1.12 kre UPDATE_FROM=${WORK_PFX}/updating.from.version
60 1.12 kre
61 1.12 kre usage()
62 1.12 kre {
63 1.17 kre printf >&2 '%s\n' '' \
64 1.17 kre "Usage: $0 [new-version-id [old-version-id]]" '' \
65 1.12 kre " where a version-id is of the form YYYYx (eg: 2018c)" \
66 1.15 kre " or '' for new-version-id (to specify only the old)" \
67 1.15 kre " and where new-version-id can have =fetch-version-id" \
68 1.16 kre " appended to specify fetching that version instead" \
69 1.16 kre " where the 'fetch-version-id' can be omitted if it" \
70 1.16 kre " is \${new-version-id}gtz - and simply using '=' means" \
71 1.16 kre " to work out the new-version-id but then use the gtz fork"
72 1.16 kre
73 1.17 kre printf >&2 '\nUsually use:\n\t\tsh %s =\n' "${0##*/}"
74 1.17 kre
75 1.12 kre exit 2
76 1.12 kre }
77 1.12 kre
78 1.12 kre fail()
79 1.12 kre {
80 1.12 kre local IFS=' '
81 1.12 kre
82 1.12 kre printf >&2 '%s\n' "Error detected:" " $*" "Aborting."
83 1.12 kre exit 1
84 1.12 kre }
85 1.12 kre
86 1.12 kre valid_vers()
87 1.12 kre {
88 1.12 kre case "$2" in
89 1.15 kre # The IANA (Eggert) standard version names
90 1.17 kre ( ${VERS_PATTERN} | ${VERS_PATTERN}[a-z] )
91 1.12 kre ;;
92 1.15 kre # The alternate (more rational) fork "global timezone" version
93 1.17 kre ( ${VERS_PATTERN}gtz | ${VERS_PATTERN}[a-z]gtz )
94 1.15 kre ;;
95 1.17 kre (*) printf >&2 '%s: %s\n' \
96 1.12 kre "Bad form for $1 version specifier '$2'" \
97 1.12 kre "should (usually) be 'YYYYx'"
98 1.12 kre return 1
99 1.12 kre ;;
100 1.12 kre esac
101 1.12 kre return 0
102 1.12 kre }
103 1.12 kre
104 1.12 kre get_curvers()
105 1.12 kre {
106 1.12 kre local LF=''
107 1.12 kre local LIST=iana-listing
108 1.12 kre local SED_SCRIPT='
109 1.12 kre /tzdata-latest.*-> /{
110 1.12 kre s/^.*-> //
111 1.12 kre s/\..*$//
112 1.12 kre s;^releases/tzdata;;p
113 1.12 kre q
114 1.12 kre }
115 1.12 kre d'
116 1.12 kre
117 1.12 kre test -d "${WORK_PFX}" &&
118 1.12 kre test -s "${WORK_PFX}/${LIST}" &&
119 1.12 kre test "${WORK_PFX}/${LIST}" -nt dist/CVS &&
120 1.12 kre LF=$(find "${WORK_PFX}" -name "${LIST}" -mtime -1 -print) &&
121 1.12 kre test -n "${LF}" &&
122 1.12 kre NEWVER=$(sed -n < "${LF}" "${SED_SCRIPT}") &&
123 1.12 kre valid_vers new "${NEWVER}" ||
124 1.12 kre
125 1.12 kre ftp >/dev/null 2>&1 -ia "${DIST_HOST}" <<- EOF &&
126 1.12 kre dir ${DIST_PATH} ${WORK_PFX}/${LIST}
127 1.12 kre quit
128 1.12 kre EOF
129 1.12 kre test -s "${WORK_PFX}/${LIST}" &&
130 1.12 kre NEWVER=$(sed -n < "${WORK_PFX}/${LIST}" "${SED_SCRIPT}") &&
131 1.12 kre valid_vers new "${NEWVER}" ||
132 1.12 kre
133 1.12 kre {
134 1.12 kre rm -f "${WORK_PFX}/${LIST}"
135 1.12 kre fail "Cannot fetch current tzdata version from ${DIST_HOST}"
136 1.12 kre }
137 1.12 kre
138 1.17 kre printf 'Updating from %s to %s\n' "${OLDVER}" "${NEWVER}"
139 1.12 kre }
140 1.12 kre
141 1.12 kre argparse()
142 1.12 kre {
143 1.15 kre local OVF OV NV OVy OVs NVy NVs
144 1.12 kre
145 1.12 kre if OVF=$(find "${WORK_PFX}" -name "${UPDATE_FROM##*/}" -mtime +2 -print)
146 1.12 kre then
147 1.12 kre # delete anything old
148 1.12 kre test -n "${OVF}" && rm -f "${OVF}"
149 1.12 kre fi
150 1.12 kre
151 1.12 kre case "$#" in
152 1.17 kre ( 0 | 1 )
153 1.12 kre # once we have obtained OLDVER once, never guess it again.
154 1.16 kre if [ -f "${UPDATE_FROM}" ]
155 1.16 kre then
156 1.16 kre OLDVER=$(cat "${UPDATE_FROM}")
157 1.16 kre elif [ -f dist/TZDATA_VERSION ]
158 1.16 kre then
159 1.16 kre OLDVER=$(cat dist/TZDATA_VERSION)
160 1.16 kre elif [ -f dist/version ]
161 1.16 kre then
162 1.16 kre OLDVER=$(cat dist/version)
163 1.16 kre fi
164 1.17 kre OLDVER=${OLDVER#tzdata} # TZDATA_VERS is tzdata-nnnnX
165 1.17 kre OLDVER=${OLDVER#-} # but the '-' is optional
166 1.17 kre OLDVERGTZ=${OLDVER} # This would have been the cvs tag
167 1.17 kre OLDVER=${OLDVER%gtz} # want the base version elsewhere
168 1.12 kre
169 1.16 kre if [ -z "${OLDVER}" ]
170 1.16 kre then
171 1.12 kre printf >&2 '%s\n' \
172 1.16 kre 'Cannot determine current installed version' \
173 1.16 kre 'Specify it on the command line.' \
174 1.16 kre ''
175 1.12 kre usage
176 1.16 kre fi
177 1.12 kre
178 1.12 kre valid_vers old "${OLDVER}" ||
179 1.12 kre fail "Calculated bad OLDVER, give as 2nd arg"
180 1.12 kre ;;
181 1.1 apb
182 1.17 kre ( 2 ) valid_vers old "$2" && OLDVER="$2" || usage
183 1.12 kre ;;
184 1.12 kre
185 1.17 kre ( * ) usage
186 1.12 kre ;;
187 1.12 kre esac
188 1.12 kre
189 1.16 kre GLOBAL=false
190 1.12 kre case "$#:$1" in
191 1.17 kre ( 0: | 1: | 2: )
192 1.12 kre ;;
193 1.17 kre ( 1:= | 2:= )
194 1.16 kre GLOBAL=true;;
195 1.17 kre ( 1:=?* | 2:=?* )
196 1.15 kre valid_vers fetch "${1#=}" && FETCHVER="${1#=}" || usage
197 1.15 kre ;;
198 1.17 kre ( 1:*=?* | 2:*=?* )
199 1.15 kre set -- "{$1%=*}" "${1#*=}"
200 1.15 kre valid_vers fetch "$2" && FETCHVER="$2" || usage
201 1.15 kre valid_vers new "$1" && NEWVER="$1" || usage
202 1.15 kre ;;
203 1.17 kre ( 1:?* | 2:?* )
204 1.12 kre valid_vers new "$1" && NEWVER="$1" || usage
205 1.12 kre ;;
206 1.17 kre ( * ) usage
207 1.12 kre ;;
208 1.12 kre esac
209 1.12 kre
210 1.12 kre test -z "${NEWVER}" && get_curvers
211 1.12 kre
212 1.16 kre if [ -z "${FETCHVER}" ]
213 1.16 kre then
214 1.17 kre if "${GLOBAL}"
215 1.16 kre then
216 1.16 kre FETCHVER=${NEWVER}gtz
217 1.16 kre else
218 1.16 kre FETCHVER=${NEWVER}
219 1.16 kre fi
220 1.16 kre fi
221 1.15 kre
222 1.15 kre case "${FETCHVER}" in
223 1.17 kre ( *gtz ) GLOBAL=true;;
224 1.17 kre ( * ) GLOBAL=false;;
225 1.15 kre esac
226 1.15 kre
227 1.16 kre if [ "${NEWVER}" = "${OLDVER}" ]
228 1.16 kre then
229 1.16 kre printf 'New and old versions both %s; nothing to do\n' \
230 1.16 kre "${NEWVER}"
231 1.17 kre docupdate
232 1.12 kre exit 0
233 1.16 kre fi
234 1.12 kre
235 1.17 kre if ! "${GLOBAL}"
236 1.17 kre then
237 1.17 kre local reply
238 1.17 kre
239 1.17 kre printf 'This will not use the GTZ variant of tzdata.\n'
240 1.17 kre read -r -p 'Is that intended? ' reply
241 1.17 kre case "${reply}" in
242 1.17 kre ([Yy]*) ;;
243 1.17 kre (*) printf 'Aborting after doing nothing\n'; exit 1;;
244 1.17 kre esac
245 1.17 kre fi
246 1.17 kre
247 1.12 kre printf '%s\n' "${OLDVER}" > "${UPDATE_FROM}" ||
248 1.12 kre fail "Unable to preserve old version ${OLDVER} in ${UPDATE_FROM}"
249 1.12 kre
250 1.15 kre # Do version upgrade test using base version names, ignoring
251 1.15 kre # the "gtz" in the "global timezone" versions, so we can
252 1.15 kre # switch back and forth between use of those as circumstances change
253 1.15 kre OV=${OLDVER%gtz}
254 1.15 kre NV=${NEWVER%gtz}
255 1.15 kre
256 1.15 kre OVy=${OV%%[!0-9]*}
257 1.15 kre OVs=${OV#${OVy}}
258 1.15 kre NVy=${NV%%[!0-9]*}
259 1.15 kre NVs=${NV#${NVy}}
260 1.15 kre
261 1.15 kre # To get all the permutations correct, we need to separate
262 1.15 kre # the year and suffix parts of the version IDs (done just above)
263 1.15 kre # and then compare them separately. The suffix is only relevant
264 1.15 kre # to the result when the years are the same.
265 1.15 kre
266 1.15 kre # We compare the length of the suffix separately to the suffix
267 1.15 kre # itself, a multi-char suffix has never happened (and is never
268 1.15 kre # likely to) - but in the event that prediction is wrong, we don't
269 1.15 kre # know (yet) what is to come after 'z' - it might be 'za' 'zb'
270 1.15 kre # ... to 'zz" then 'zza' ... or it might be 'aa' 'ab' ... 'az' 'ba'...
271 1.15 kre # we need to handle both possibilities. Two things stand out from
272 1.15 kre # those: 1. a longer suffix is always going to be for a newer version
273 1.15 kre # than a shorter one; 2. equal length suffixes can be compared as
274 1.15 kre # strings
275 1.15 kre
276 1.15 kre if [ "${OVy}" -gt "${NVy}" ] || {
277 1.15 kre [ "${OVy}" -eq "${NVy}" ] && {
278 1.15 kre [ "${#OVs}" -gt "${#NVs}" ] ||
279 1.15 kre LC_COLLATE=C [ "${OVs}" '>' "${NVs}" ]
280 1.12 kre }
281 1.15 kre } then
282 1.15 kre local reply
283 1.15 kre
284 1.15 kre printf '%s\n' "Update would revert ${OLDVER} to ${NEWVER}"
285 1.15 kre read -p "Is reversion intended? " reply
286 1.15 kre case "${reply}" in
287 1.17 kre ([Yy]*) ;;
288 1.17 kre (*) printf '%s\n' OK. Aborted.
289 1.15 kre rm -f "${UPDATE_FROM}"
290 1.15 kre exit 1
291 1.15 kre ;;
292 1.15 kre esac
293 1.15 kre fi
294 1.12 kre
295 1.12 kre return 0
296 1.12 kre }
297 1.12 kre
298 1.12 kre setup_versions()
299 1.12 kre {
300 1.12 kre # Uppercase variants of OLDVER and NEWVER
301 1.17 kre OLDVER_UC="$( printf '%s\n' "${OLDVERGTZ}" | tr 'a-z' 'A-Z' )"
302 1.17 kre NEWVER_UC="$( printf '%s\n' "${NEWVER}" | tr 'a-z' 'A-Z' )"
303 1.12 kre
304 1.12 kre # Tags for use with version control systems
305 1.12 kre CVSOLDTAG="TZDATA${OLDVER_UC}"
306 1.12 kre CVSNEWTAG="TZDATA${NEWVER_UC}"
307 1.12 kre CVSBRANCHTAG="TZDATA"
308 1.12 kre GITHUBTAG="${NEWVER}"
309 1.12 kre
310 1.17 kre if "${GLOBAL}" && [ "${CVSNEWTAG%GTZ}" = "${CVSNEWTAG}" ]
311 1.15 kre then
312 1.15 kre CVSNEWTAG=${CVSNEWTAG}GTZ
313 1.15 kre fi
314 1.15 kre
315 1.12 kre # URLs for fetching distribution files, etc.
316 1.17 kre if "${GLOBAL}"
317 1.15 kre then
318 1.16 kre DISTURL=${GTZURL}/${FETCHVER}/tzdata${FETCHVER}.tar.gz
319 1.15 kre unset SIGURL
320 1.15 kre else
321 1.15 kre DISTURL="ftp://${DIST_HOST}/${DIST_PATH}/${DIST_FILES}"
322 1.15 kre DISTURL="${DISTURL}/tzdata${NEWVER}.tar.gz"
323 1.15 kre SIGURL="${DISTURL}.asc"
324 1.15 kre fi
325 1.12 kre NEWSURL="https://github.com/eggert/tz/raw/${GITHUBTAG}/NEWS"
326 1.12 kre
327 1.12 kre # Directories
328 1.12 kre REPODIR="src/external/public-domain/tz/dist"
329 1.12 kre # relative to the NetBSD CVS repo
330 1.12 kre TZDISTDIR="$(pwd)/dist" # should be .../external/public-domain/tz/dist
331 1.12 kre WORKDIR="${WORK_PFX}/${NEWVER}"
332 1.12 kre EXTRACTDIR="${WORKDIR}/extract"
333 1.12 kre
334 1.12 kre # Files in the work directory
335 1.12 kre DISTFILE="${WORKDIR}/${DISTURL##*/}"
336 1.12 kre SIGFILE="${DISTFILE}.asc"
337 1.12 kre PGPVERIFYLOG="${WORKDIR}/pgpverify.log"
338 1.12 kre NEWSFILE="${WORKDIR}/NEWS"
339 1.12 kre NEWSTRIMFILE="${WORKDIR}/NEWS.trimmed"
340 1.12 kre IMPORTMSGFILE="${WORKDIR}/import.msg"
341 1.12 kre IMPORTDONEFILE="${WORKDIR}/import.done"
342 1.12 kre MERGSMSGFILE="${WORKDIR}/merge.msg"
343 1.12 kre MERGEDONEFILE="${WORKDIR}/merge.done"
344 1.17 kre FILECONTENTCHECKDONE="${WORKDIR}/filecheck.done"
345 1.12 kre COMMITMERGEDONEFILE="${WORKDIR}/commitmerge.done"
346 1.12 kre
347 1.12 kre printf '%s\n' "${CVSOLDTAG}" > "${WORK_PFX}/updating_from"
348 1.12 kre }
349 1.9 agc
350 1.1 apb DOIT()
351 1.1 apb {
352 1.1 apb local really_do_it=false
353 1.1 apb local reply
354 1.1 apb
355 1.17 kre printf 'In directory %s\n' "$(pwd)"
356 1.17 kre printf 'ABOUT TO DO: %s\n' "$(shell_quote "$@")"
357 1.1 apb read -p "Really do it? [yes/no/quit] " reply
358 1.1 apb case "${reply}" in
359 1.17 kre ([yY]*) really_do_it=true ;;
360 1.17 kre ([nN]*) really_do_it=false ;;
361 1.17 kre ([qQ]*)
362 1.17 kre printf 'Aborting\n'
363 1.1 apb return 1
364 1.1 apb ;;
365 1.17 kre (*) printf 'Huh?\n'
366 1.12 kre return 1
367 1.12 kre ;;
368 1.1 apb esac
369 1.17 kre if "$really_do_it"; then
370 1.17 kre printf 'REALLY DOING IT NOW...\n'
371 1.1 apb "$@"
372 1.1 apb else
373 1.17 kre printf 'NOT DOING THE ABOVE COMMAND\n'
374 1.1 apb fi
375 1.1 apb }
376 1.1 apb
377 1.1 apb # Quote args to make them safe in the shell.
378 1.1 apb # Usage: quotedlist="$(shell_quote args...)"
379 1.1 apb #
380 1.1 apb # After building up a quoted list, use it by evaling it inside
381 1.1 apb # double quotes, like this:
382 1.1 apb # eval "set -- $quotedlist"
383 1.1 apb # or like this:
384 1.1 apb # eval "\$command $quotedlist \$filename"
385 1.1 apb #
386 1.1 apb shell_quote()
387 1.12 kre (
388 1.1 apb local result=''
389 1.1 apb local arg qarg
390 1.1 apb LC_COLLATE=C ; export LC_COLLATE # so [a-zA-Z0-9] works in ASCII
391 1.1 apb for arg in "$@" ; do
392 1.1 apb case "${arg}" in
393 1.17 kre ('')
394 1.1 apb qarg="''"
395 1.1 apb ;;
396 1.17 kre (*[!-./a-zA-Z0-9]*)
397 1.1 apb # Convert each embedded ' to '\'',
398 1.1 apb # then insert ' at the beginning of the first line,
399 1.1 apb # and append ' at the end of the last line.
400 1.1 apb # Finally, elide unnecessary '' pairs at the
401 1.1 apb # beginning and end of the result and as part of
402 1.1 apb # '\'''\'' sequences that result from multiple
403 1.13 kre # adjacent quotes in the input.
404 1.12 kre qarg="$(printf '%s\n' "$arg" | \
405 1.1 apb ${SED:-sed} -e "s/'/'\\\\''/g" \
406 1.1 apb -e "1s/^/'/" -e "\$s/\$/'/" \
407 1.1 apb -e "1s/^''//" -e "\$s/''\$//" \
408 1.1 apb -e "s/'''/'/g"
409 1.1 apb )"
410 1.1 apb ;;
411 1.17 kre (*)
412 1.1 apb # Arg is not the empty string, and does not contain
413 1.1 apb # any unsafe characters. Leave it unchanged for
414 1.1 apb # readability.
415 1.1 apb qarg="${arg}"
416 1.1 apb ;;
417 1.1 apb esac
418 1.1 apb result="${result}${result:+ }${qarg}"
419 1.1 apb done
420 1.12 kre printf '%s\n' "$result"
421 1.12 kre )
422 1.12 kre
423 1.12 kre validate_pwd()
424 1.12 kre {
425 1.12 kre local P="$(pwd)" || return 1
426 1.12 kre
427 1.12 kre test -d "${P}" &&
428 1.12 kre test -d "${P}/CVS" &&
429 1.12 kre test -d "${P}/dist" &&
430 1.12 kre test -f "${P}/dist/zone.tab" &&
431 1.12 kre test -f "${P}/tzdata2netbsd" || {
432 1.12 kre printf >&2 '%s\n' "Please change to the correct directory"
433 1.12 kre return 1
434 1.12 kre }
435 1.12 kre
436 1.12 kre test -f "${P}/CVS/Tag" && {
437 1.12 kre
438 1.12 kre # Here (for local use only) if needed for private branch work
439 1.12 kre # insert tests for the value of $(cat "${P}/CVS/Tag") and
440 1.12 kre # allow your private branch tag to pass. Eg:
441 1.12 kre
442 1.12 kre # case "$(cat "${P}/CVS/Tag")" in
443 1.17 kre # (my-branch-name) return 0;;
444 1.12 kre # esac
445 1.12 kre
446 1.12 kre # Do not commit a version of this script modified that way,
447 1.12 kre # (not even on the private branch) - keep it as a local
448 1.12 kre # modified file. (This script will not commit it.)
449 1.12 kre
450 1.12 kre printf >&2 '%s\n' \
451 1.12 kre "This script should be run in a checkout of HEAD only"
452 1.12 kre return 1
453 1.12 kre }
454 1.12 kre
455 1.12 kre return 0
456 1.12 kre }
457 1.1 apb
458 1.1 apb findcvsroot()
459 1.1 apb {
460 1.1 apb [ -n "${CVSROOT}" ] && return 0
461 1.17 kre CVSROOT="$( cat ./CVS/Root )" || {
462 1.17 kre printf 'No CVS/Root in %s\n' "$(pwd)"
463 1.17 kre return 1
464 1.17 kre }
465 1.1 apb [ -n "${CVSROOT}" ] && return 0
466 1.17 kre printf >&2 'Failed to set CVSROOT value\n'
467 1.1 apb return 1
468 1.1 apb }
469 1.1 apb
470 1.12 kre mkworkpfx()
471 1.12 kre {
472 1.12 kre mkdir -p "${WORK_PFX}" || fail "Unable to make missing ${WORK_PFX}"
473 1.12 kre }
474 1.1 apb mkworkdir()
475 1.1 apb {
476 1.12 kre mkdir -p "${WORKDIR}" || fail "Unable to make missing ${WORKDIR}"
477 1.1 apb }
478 1.1 apb
479 1.16 kre cvsupdate()
480 1.16 kre (
481 1.16 kre # Make sure our working directory is up to date (and HEAD)
482 1.16 kre cd "${TZBASE}/dist" || exit 1
483 1.16 kre cvs -d "${CVSROOT}" -q update -AdP || exit 2
484 1.16 kre )
485 1.16 kre
486 1.1 apb fetch()
487 1.1 apb {
488 1.12 kre [ -f "${DISTFILE}" ] || ftp -o "${DISTFILE}" "${DISTURL}" ||
489 1.12 kre fail "fetch of ${DISTFILE} failed"
490 1.15 kre
491 1.15 kre if [ -n "${SIGURL}" ]
492 1.15 kre then
493 1.15 kre [ -f "${SIGFILE}" ] || ftp -o "${SIGFILE}" "${SIGURL}" ||
494 1.15 kre fail "fetch of ${SIGFILE} failed"
495 1.15 kre fi
496 1.15 kre
497 1.12 kre [ -f "${NEWSFILE}" ] || ftp -o "${NEWSFILE}" "${NEWSURL}" ||
498 1.12 kre fail "fetch of ${NEWSFILE} failed"
499 1.1 apb }
500 1.1 apb
501 1.1 apb checksig()
502 1.1 apb {
503 1.17 kre {
504 1.17 kre gpg --verify "${SIGFILE}" "${DISTFILE}"
505 1.17 kre printf 'gpg exit status %s\n' "$?"
506 1.17 kre } 2>&1 |
507 1.17 kre tee "${PGPVERIFYLOG}"
508 1.1 apb
509 1.1 apb # The output should contain lines that match all the following regexps
510 1.1 apb #
511 1.17 kre while read line
512 1.17 kre do
513 1.17 kre if ! grep -E -q -e "^${line}\$" "${PGPVERIFYLOG}"
514 1.17 kre then
515 1.17 kre printf >&2 'Failed to verify signature: %s\n' "${line}"
516 1.1 apb return 1
517 1.1 apb fi
518 1.1 apb done <<'EOF'
519 1.11 kre gpg: Signature made .* using RSA key ID (62AA7E34|44AD418C)
520 1.1 apb gpg: Good signature from "Paul Eggert <eggert (a] cs.ucla.edu>"
521 1.1 apb gpg exit status 0
522 1.1 apb EOF
523 1.1 apb }
524 1.1 apb
525 1.1 apb extract()
526 1.1 apb {
527 1.1 apb [ -f "${EXTRACTDIR}/zone.tab" ] && return
528 1.1 apb mkdir -p "${EXTRACTDIR}"
529 1.1 apb tar -z -xf "${DISTFILE}" -C "${EXTRACTDIR}"
530 1.1 apb }
531 1.1 apb
532 1.16 kre rflist()
533 1.16 kre (
534 1.16 kre test "${1}" && cd "${1}" && find * -print | sort
535 1.16 kre )
536 1.16 kre
537 1.16 kre zonelists()
538 1.16 kre {
539 1.16 kre [ -f "${WORKDIR}"/addedzones ] && return
540 1.16 kre
541 1.16 kre rm -fr "${WORK_PFX}"/oldzones "${WORK_PFX}"/newzones
542 1.16 kre
543 1.16 kre (
544 1.16 kre cd "${TZBASE}/share/zoneinfo" || exit 1
545 1.16 kre
546 1.16 kre make TOOL_ZIC=/usr/sbin/zic \
547 1.16 kre DESTDIR= \
548 1.16 kre TZBUILDDIR="${WORK_PFX}"/oldzones \
549 1.16 kre TZDIR="${WORK_PFX}"/oldzones \
550 1.16 kre TZDISTDIR="${TZBASE}"/dist \
551 1.16 kre posix_only >/dev/null 2>&1
552 1.16 kre
553 1.16 kre ) || fail 'Unable to compile old zone data files'
554 1.16 kre
555 1.16 kre (
556 1.16 kre cd "${TZBASE}/share/zoneinfo" || exit 1
557 1.16 kre
558 1.16 kre make TOOL_ZIC=/usr/sbin/zic \
559 1.16 kre DESTDIR= \
560 1.16 kre TZBUILDDIR="${WORK_PFX}"/newzones \
561 1.16 kre TZDIR="${WORK_PFX}"/newzones \
562 1.16 kre TZDISTDIR="${EXTRACTDIR}" \
563 1.16 kre posix_only >/dev/null 2>&1
564 1.16 kre
565 1.16 kre ) || fail 'Unable to compile new zone data files'
566 1.16 kre
567 1.16 kre rflist "${WORK_PFX}"/oldzones > "${WORKDIR}"/oldzones
568 1.16 kre rflist "${WORK_PFX}"/newzones > "${WORKDIR}"/newzones
569 1.16 kre
570 1.16 kre if cmp -s "${WORKDIR}"/oldzones "${WORKDIR}"/newzones >/dev/null
571 1.16 kre then
572 1.17 kre printf 'No zones added or deleted by this update\n'
573 1.16 kre > "${WORKDIR}"/removedzones
574 1.16 kre > "${WORKDIR}"/addedzones
575 1.16 kre return 0
576 1.16 kre fi
577 1.16 kre
578 1.16 kre comm -23 "${WORKDIR}"/oldzones "${WORKDIR}"/newzones \
579 1.16 kre > "${WORKDIR}"/removedzones
580 1.16 kre
581 1.16 kre test "${REMOVEOK:-no}" != yes && test -s "${WORKDIR}"/removedzones && {
582 1.16 kre printf '%s\n' 'This update wants to remove these zone files:' ''
583 1.16 kre sed 's/^/ /' < "${WORKDIR}"/removedzones
584 1.16 kre printf '%s\n' '' 'It probably should not' ''
585 1.16 kre
586 1.16 kre printf 'If this is OK, rerun this script with REMOVEOK=yes\n'
587 1.16 kre printf 'Otherwise, fix the problem, and then rerun the script\n'
588 1.16 kre exit 1
589 1.16 kre }
590 1.16 kre
591 1.16 kre comm -13 "${WORKDIR}"/oldzones "${WORKDIR}"/newzones \
592 1.16 kre > "${WORKDIR}"/addedzones
593 1.16 kre
594 1.16 kre test -s "${WORKDIR}"/addedzones && {
595 1.16 kre printf '%s\n' '' '********************************* NOTE:' \
596 1.16 kre '********************************* New Zones Created' \
597 1.16 kre ''
598 1.16 kre sed 's/^/ /' < "${WORKDIR}"/addedzones
599 1.16 kre printf '%s\n' '' '*********************************' ''
600 1.16 kre }
601 1.16 kre
602 1.16 kre return 0
603 1.16 kre }
604 1.16 kre
605 1.16 kre updatedzones()
606 1.16 kre {
607 1.16 kre [ -f "${WORKDIR}"/.zonesOK ] && return
608 1.16 kre
609 1.16 kre rm -fr "${WORK_PFX}"/updzones
610 1.16 kre
611 1.16 kre (
612 1.16 kre cd "${TZBASE}/share/zoneinfo" || exit 1
613 1.16 kre
614 1.16 kre make TOOL_ZIC=/usr/sbin/zic \
615 1.16 kre DESTDIR= \
616 1.16 kre TZBUILDDIR="${WORK_PFX}"/updzones \
617 1.16 kre TZDIR="${WORK_PFX}"/updzones \
618 1.16 kre TZDISTDIR="${TZBASE}"/dist \
619 1.16 kre posix_only >/dev/null 2>&1
620 1.16 kre
621 1.16 kre ) || fail 'Unable to compile updated zone data. HELP'
622 1.16 kre
623 1.16 kre rflist "${WORK_PFX}"/updzones > "${WORKDIR}"/updzones
624 1.16 kre
625 1.16 kre cmp -s "${WORKDIR}"/newzones "${WORKDIR}"/updzones || {
626 1.16 kre
627 1.16 kre printf '%s\n' '' '*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*' \
628 1.16 kre 'After cvs work, zones created are not as intended' \
629 1.16 kre '-------------------------------------------------' \
630 1.16 kre 'Zones not created but should have been:'
631 1.16 kre comm -23 "${WORKDIR}"/newzones "${WORKDIR}"/updzones |
632 1.16 kre sed 's/^/ /'
633 1.16 kre printf '%s\n' \
634 1.16 kre '-------------------------------------------------' \
635 1.16 kre 'Zones created that should not have been:'
636 1.16 kre comm -13 "${WORKDIR}"/newzones "${WORKDIR}"/updzones |
637 1.16 kre sed 's/^/ /'
638 1.17 kre printf '%s\n' \
639 1.16 kre '-------------------------------------------------'
640 1.16 kre
641 1.16 kre fail 'cvs import/merge/update/commit botch'
642 1.16 kre }
643 1.16 kre
644 1.16 kre > "${WORKDIR}"/.zonesOK
645 1.16 kre }
646 1.16 kre
647 1.2 apb addnews()
648 1.2 apb {
649 1.2 apb [ -f "${EXTRACTDIR}/NEWS" ] && return
650 1.2 apb cp -p "${NEWSFILE}" "${EXTRACTDIR}"/NEWS
651 1.2 apb }
652 1.2 apb
653 1.1 apb # Find the relevant part of the NEWS file for all releases between
654 1.1 apb # OLDVER and NEWVER, and save them to NEWSTRIMFILE.
655 1.1 apb #
656 1.1 apb trimnews()
657 1.1 apb {
658 1.1 apb [ -s "${NEWSTRIMFILE}" ] && return
659 1.1 apb awk -v oldver="${OLDVER}" -v newver="${NEWVER}" \
660 1.1 apb '
661 1.1 apb BEGIN {inrange = 0}
662 1.1 apb /^Release [0-9]+[a-z]+ - .*/ {
663 1.1 apb # "Release <version> - <date>"
664 1.12 kre # Note: must handle transition from 2018z to 2018aa
665 1.12 kre # Assumptions: OLDVER and NEWVER have been sanitized,
666 1.12 kre # and format of NEWS file does not alter (and
667 1.12 kre # contains valid data)
668 1.12 kre inrange = ((length($2) > length(oldver) || \
669 1.12 kre $2 > oldver) && \
670 1.12 kre (length($2) < newver || $2 <= newver))
671 1.1 apb }
672 1.1 apb // { if (inrange) print; }
673 1.12 kre ' \
674 1.1 apb <"${NEWSFILE}" >"${NEWSTRIMFILE}"
675 1.16 kre
676 1.17 kre if "${GLOBAL}"
677 1.16 kre then
678 1.16 kre printf '%s\n' "tzdata-${NEWVER}gtz"
679 1.16 kre else
680 1.16 kre printf '%s\n' "tzdata-${NEWVER}"
681 1.16 kre fi > ${TZDISTDIR}/TZDATA_VERSION
682 1.1 apb }
683 1.1 apb
684 1.1 apb # Create IMPORTMSGFILE from NEWSTRIMFILE, by ignoring some sections,
685 1.1 apb # keeping only the first sentence from paragraphs in other sections,
686 1.1 apb # and changing the format.
687 1.1 apb #
688 1.1 apb # The result should be edited by hand before performing a cvs commit.
689 1.1 apb # A message to that effect is inserted at the beginning of the file.
690 1.1 apb #
691 1.1 apb mkimportmsg()
692 1.1 apb {
693 1.1 apb [ -s "${IMPORTMSGFILE}" ] && return
694 1.1 apb { cat <<EOF
695 1.1 apb EDIT ME: Edit this file and then delete the lines marked "EDIT ME".
696 1.1 apb EDIT ME: This file will be used as a log message for the "cvs commit" that
697 1.1 apb EDIT ME: imports tzdata${NEWVER}. The initial contents of this file were
698 1.1 apb EDIT ME: generated from ${NEWSFILE}.
699 1.1 apb EDIT ME:
700 1.1 apb EOF
701 1.1 apb awk -v oldver="${OLDVER}" -v newver="${NEWVER}" \
702 1.2 apb -v disturl="${DISTURL}" -v newsurl="${NEWSURL}" \
703 1.1 apb '
704 1.1 apb BEGIN {
705 1.1 apb bullet = " * ";
706 1.1 apb indent = " ";
707 1.1 apb blankline = 0;
708 1.1 apb goodsection = 0;
709 1.1 apb havesentence = 0;
710 1.1 apb print "Import tzdata"newver" from "disturl;
711 1.4 apb #print "and NEWS file from "newsurl;
712 1.1 apb }
713 1.1 apb /^Release/ {
714 1.1 apb # "Release <version> - <date>"
715 1.1 apb ver = $2;
716 1.1 apb date = gensub(".* - ", "", 1, $0);
717 1.1 apb print "";
718 1.1 apb print "Summary of changes in tzdata"ver \
719 1.1 apb " ("date"):";
720 1.1 apb }
721 1.1 apb /^$/ { blankline = 1; havesentence = 0; }
722 1.14 kre /^ Changes / { goodsection = 0; }
723 1.14 kre /^ Changes to future timestamps/ { goodsection = 1; }
724 1.14 kre /^ Changes to past timestamps/ { goodsection = 1; }
725 1.14 kre /^ Changes to documentation/ || \
726 1.14 kre /^ Changes to commentary/ {
727 1.1 apb t = gensub("^ *", "", 1, $0);
728 1.1 apb t = gensub("\\.*$", ".", 1, t);
729 1.1 apb print bullet t;
730 1.1 apb goodsection = 0;
731 1.1 apb }
732 1.1 apb /^ .*/ && goodsection {
733 1.1 apb # In a paragraph in a "good" section.
734 1.1 apb # Ignore leading spaces, and ignore anything
735 1.1 apb # after the first sentence.
736 1.1 apb # First line of paragraph gets a bullet.
737 1.1 apb t = gensub("^ *", "", 1, $0);
738 1.1 apb t = gensub("\\. .*", ".", 1, t);
739 1.1 apb if (blankline) print bullet t;
740 1.1 apb else if (! havesentence) print indent t;
741 1.1 apb havesentence = (havesentence || (t ~ "\\.$"));
742 1.1 apb }
743 1.1 apb /./ { blankline = 0; }
744 1.12 kre ' \
745 1.1 apb <"${NEWSTRIMFILE}"
746 1.1 apb } >"${IMPORTMSGFILE}"
747 1.16 kre
748 1.16 kre if [ -s "${WORKDIR}"/addedzones ]
749 1.16 kre then
750 1.16 kre printf '%s\n' '' 'Zones added by this update:'
751 1.16 kre sed 's/^/ /' < "${WORKDIR}"/addedzones
752 1.16 kre fi >> "${IMPORTMSGFILE}"
753 1.16 kre
754 1.16 kre if [ -s "${WORKDIR}"/removedzones ]
755 1.16 kre then
756 1.16 kre printf '%s\n' '' 'Zones removed by this update:'
757 1.16 kre sed 's/^/ /' < "${WORKDIR}"/removedzones
758 1.16 kre fi >> "${IMPORTMSGFILE}"
759 1.16 kre
760 1.1 apb }
761 1.1 apb
762 1.1 apb editimportmsg()
763 1.1 apb {
764 1.16 kre if [ -s "${IMPORTMSGFILE}" ] && ! grep -q '^EDIT' "${IMPORTMSGFILE}"
765 1.1 apb then
766 1.1 apb return 0 # file has already been edited
767 1.1 apb fi
768 1.1 apb # Pass both IMPORTMSGFILE and NEWSFILE to the editor, so that the
769 1.1 apb # user can easily consult NEWSFILE while editing IMPORTMSGFILE.
770 1.9 agc ${EDITOR} "${IMPORTMSGFILE}" "${NEWSFILE}"
771 1.1 apb }
772 1.1 apb
773 1.1 apb cvsimport()
774 1.1 apb {
775 1.6 apb if [ -e "${IMPORTDONEFILE}" ]; then
776 1.5 apb cat >&2 <<EOF
777 1.5 apb The CVS import has already been performed.
778 1.5 apb EOF
779 1.5 apb return 0
780 1.5 apb fi
781 1.16 kre if ! [ -s "${IMPORTMSGFILE}" ] || grep -q '^EDIT' "${IMPORTMSGFILE}"
782 1.1 apb then
783 1.1 apb cat >&2 <<EOF
784 1.1 apb The message file ${IMPORTMSGFILE}
785 1.1 apb has not been properly edited.
786 1.1 apb Not performing cvs import.
787 1.1 apb EOF
788 1.1 apb return 1
789 1.1 apb fi
790 1.1 apb ( cd "${EXTRACTDIR}" &&
791 1.16 kre DOIT cvs -d "${CVSROOT}" import -I ! -m "$(cat "${IMPORTMSGFILE}")" \
792 1.1 apb "${REPODIR}" "${CVSBRANCHTAG}" "${CVSNEWTAG}"
793 1.6 apb ) && touch "${IMPORTDONEFILE}"
794 1.1 apb }
795 1.1 apb
796 1.1 apb cvsmerge()
797 1.5 apb {
798 1.3 apb
799 1.3 apb cd "${TZDISTDIR}" || exit 1
800 1.16 kre if [ -e "${MERGEDONEFILE}" ]
801 1.16 kre then
802 1.5 apb cat >&2 <<EOF
803 1.5 apb The CVS merge has already been performed.
804 1.5 apb EOF
805 1.5 apb return 0
806 1.5 apb fi
807 1.16 kre DOIT cvs -d "${CVSROOT}" update -j"${CVSOLDTAG}" -j"${CVSNEWTAG}" &&
808 1.16 kre touch "${MERGEDONEFILE}"
809 1.16 kre printf '%s\n' ================================== \
810 1.16 kre 'The following differences exist between the merge results' \
811 1.16 kre 'and the imported files:' '================================='
812 1.17 kre diff -ur "${EXTRACTDIR}" . || :
813 1.16 kre printf '%s\n' ==================================
814 1.5 apb }
815 1.1 apb
816 1.1 apb resolveconflicts()
817 1.1 apb {
818 1.5 apb cd "${TZDISTDIR}" || exit 1
819 1.5 apb if grep -l '^[<=>][<=>][<=>]' *
820 1.5 apb then
821 1.5 apb cat <<EOF
822 1.5 apb There appear to be conflicts in the files listed above.
823 1.5 apb Resolve conflicts, then re-run this script.
824 1.1 apb EOF
825 1.5 apb return 1
826 1.5 apb fi
827 1.1 apb }
828 1.1 apb
829 1.17 kre checkfilecontents()
830 1.17 kre (
831 1.17 kre if [ -e "${FILECONTENTCHECKDONE}" ]
832 1.17 kre then
833 1.17 kre printf 'Repository file contents checked already\n'
834 1.17 kre exit 0
835 1.17 kre fi
836 1.17 kre
837 1.17 kre set +e +f
838 1.17 kre
839 1.17 kre auto=false
840 1.17 kre
841 1.17 kre cd "${EXTRACTDIR}" || exit 1
842 1.17 kre set -- *
843 1.17 kre
844 1.17 kre if test "$1" = '*'
845 1.17 kre then
846 1.17 kre if [ "$#" -eq 1 ] && ! [ -e "$1" ]
847 1.17 kre then
848 1.17 kre printf 'No files in "%s" !!\nAborting.\n' \
849 1.17 kre "${EXTRACTDIR}"
850 1.17 kre exit 1
851 1.17 kre fi
852 1.17 kre printf \
853 1.17 kre 'A file named "*" exists in "%s" !!\nDanger!!\nAborting.\n'\
854 1.17 kre "${EXTRACTDIR}"
855 1.17 kre exit 1
856 1.17 kre fi
857 1.17 kre
858 1.17 kre unset -v LESS MORE
859 1.17 kre
860 1.17 kre exit=0
861 1.17 kre cd "${TZDISTDIR}" || exit 1
862 1.17 kre
863 1.17 kre for file
864 1.17 kre do
865 1.17 kre if ! test -e "${file}"
866 1.17 kre then
867 1.17 kre printf 'In distribution but not in new tree: %s\n' \
868 1.17 kre "${file}"
869 1.17 kre cp "${EXTRACTDIR}${file}" .
870 1.17 kre DOIT cvs -d "${CVSROOT}" add \
871 1.17 kre -m "Added by ${NEWVER}" "${file}"
872 1.17 kre continue
873 1.17 kre fi
874 1.17 kre
875 1.17 kre cmp -s "${EXTRACTDIR}/${file}" "${file}" && continue
876 1.17 kre
877 1.17 kre if "${auto}"
878 1.17 kre then
879 1.17 kre cp -p "${EXTRACTDIR}/${file}" "${file}"
880 1.17 kre continue
881 1.17 kre fi
882 1.17 kre
883 1.17 kre printf 'Differences in "%s" (- existing + updated)\n\n' \
884 1.17 kre "${file}"
885 1.17 kre diff -u "${file}" "${EXTRACTDIR}/${file}" | more
886 1.17 kre read -rp "Update ${file} to new version? (y/n/all)" reply
887 1.17 kre case "${reply}" in
888 1.17 kre ([Nn]*) continue;;
889 1.17 kre ([Yy]*|[Aa]|[Aa]ll) ;;
890 1.17 kre ([Qq]*) exit 1;;
891 1.17 kre (*) printf 'Unexpected reply, abort.\n'
892 1.17 kre exit 1;;
893 1.17 kre esac
894 1.17 kre
895 1.17 kre cp -p "${EXTRACTDIR}/${file}" "${file}"
896 1.17 kre
897 1.17 kre case "${reply}" in
898 1.17 kre ([Aa]*) auto=true;;
899 1.17 kre esac
900 1.17 kre done
901 1.17 kre
902 1.17 kre set -- *
903 1.17 kre LIST=
904 1.17 kre for file # nb: continue if there are no files, $1='*'
905 1.17 kre do
906 1.17 kre if test "${file}" = TZDATA_VERSION ||
907 1.17 kre test "${file}" = CVS ||
908 1.17 kre test -e "${EXTRACTDIR}/${file}"
909 1.17 kre then
910 1.17 kre continue
911 1.17 kre fi
912 1.17 kre printf 'File "%s" no longer exists in %s\n' \
913 1.17 kre "${file}" "${NEWVER}"
914 1.17 kre LIST="${LIST} '${file}'"
915 1.17 kre done
916 1.17 kre
917 1.17 kre eval set -- ${LIST}
918 1.17 kre while :
919 1.17 kre do
920 1.17 kre case $# in
921 1.17 kre (0) break;;
922 1.17 kre (1) M='this file';;
923 1.17 kre (*) M='these files';;
924 1.17 kre esac
925 1.17 kre
926 1.17 kre read -rp "OK to remove $M from the repository? " reply
927 1.17 kre case "${reply}" in
928 1.17 kre ([Yy]*) ;;
929 1.17 kre ([Nn]*) break;;
930 1.17 kre (*) exit 1;;
931 1.17 kre esac
932 1.17 kre
933 1.17 kre rm -f "$@"
934 1.17 kre DOIT cvs -d "${CVSROOT}" remove "${@}"
935 1.17 kre done
936 1.17 kre
937 1.17 kre touch "${FILECONTENTCHECKDONE}" || exit 1
938 1.17 kre
939 1.17 kre exit "${exit}"
940 1.17 kre )
941 1.17 kre
942 1.1 apb cvscommitmerge()
943 1.5 apb {
944 1.3 apb cd "${TZDISTDIR}" || exit 1
945 1.1 apb if grep -l '^[<=>][<=>][<=>]' *
946 1.1 apb then
947 1.1 apb cat >&2 <<EOF
948 1.1 apb There still appear to be conflicts in the files listed above.
949 1.1 apb Not performing cvs commit.
950 1.1 apb EOF
951 1.1 apb return 1
952 1.1 apb fi
953 1.6 apb if [ -e "${COMMITMERGEDONEFILE}" ]; then
954 1.5 apb cat >&2 <<EOF
955 1.5 apb The CVS commmit (of the merge result) has already been performed.
956 1.5 apb EOF
957 1.5 apb return 0
958 1.5 apb fi
959 1.16 kre DOIT cvs -d "${CVSROOT}" commit -m "Merge tzdata${NEWVER}" &&
960 1.16 kre touch "${COMMITMERGEDONEFILE}"
961 1.16 kre }
962 1.16 kre
963 1.16 kre setlistupdate()
964 1.16 kre {
965 1.16 kre if [ -s "${WORKDIR}"/addedzones ] ||
966 1.16 kre [ -s "${WORKDIR}"/removedzones ]
967 1.16 kre then (
968 1.16 kre # Do all the preparatory work first, so
969 1.16 kre # when we get to manipulating the sets list file
970 1.16 kre # it all happens quickly...
971 1.16 kre
972 1.16 kre while read file
973 1.16 kre do
974 1.16 kre printf '\\!zoneinfo/%s!{ %s ; %s ; }\n' \
975 1.16 kre "${file}" \
976 1.16 kre 's/sys-share /obsolete /' \
977 1.16 kre 's/ share$/ obsolete/'
978 1.16 kre done < "${WORKDIR}"/removedzones > "${WORKDIR}/sedcmds"
979 1.16 kre
980 1.16 kre while read file
981 1.16 kre do
982 1.16 kre P=./usr/share/zoneinfo/"${file}"
983 1.16 kre T2=' '
984 1.16 kre case "$(( 48 - ${#P} ))" in
985 1.17 kre (-*|0) T2=' ' T=' ' ;;
986 1.17 kre ([12345678]) T=' ' ;;
987 1.17 kre (9|1[0123456]) T=' ';;
988 1.17 kre (1[789]|2[01234]) T=' ';;
989 1.17 kre (2[5-9]|3[012])
990 1.16 kre T=' ';;
991 1.16 kre # the following cases can't happen,
992 1.16 kre # but for completeness...
993 1.17 kre (3[3-9])
994 1.16 kre T=' ';;
995 1.17 kre (*) T=' '
996 1.16 kre T="${T} " ;;
997 1.16 kre esac
998 1.16 kre
999 1.16 kre if [ -d "${WORKDIR}/newzones/${file}" ]
1000 1.16 kre then
1001 1.16 kre printf '%s%sbase-sys-share\n' \
1002 1.16 kre "${P}" "${T}"
1003 1.16 kre continue
1004 1.16 kre fi
1005 1.16 kre
1006 1.16 kre printf '%s%sbase-sys-share%sshare\n' \
1007 1.16 kre "${P}" "${T}" "${T2}"
1008 1.16 kre
1009 1.16 kre # Deal with possibility that a new file
1010 1.16 kre # might have previously existed, and then
1011 1.16 kre # been deleted - marked obsolete
1012 1.16 kre printf '\\!^%s .*obsolete!d\n' "${P}" \
1013 1.16 kre >> "${WORKDIR}/sedcmds"
1014 1.16 kre
1015 1.16 kre done < "${WORKDIR}"/addedzones > "${WORKDIR}/setadded"
1016 1.16 kre
1017 1.16 kre printf '$r %s\n' "${WORKDIR}/setadded" \
1018 1.16 kre >> "${WORKDIR}/sedcmds"
1019 1.16 kre
1020 1.16 kre if ! [ -s "${WORKDIR}/sedcmds" ] # impossible?
1021 1.16 kre then
1022 1.16 kre exit 0
1023 1.16 kre fi
1024 1.16 kre
1025 1.16 kre MSG=$(
1026 1.16 kre printf 'tzdata update to %s\n' "$NEWVER"
1027 1.16 kre if [ -s "${WORKDIR}"/addedzones ]
1028 1.16 kre then
1029 1.16 kre printf 'Added zoneinfo files:\n'
1030 1.16 kre sed 's/^/ /' \
1031 1.16 kre < "${WORKDIR}"/addedzones
1032 1.16 kre fi
1033 1.16 kre if [ -s "${WORKDIR}"/removedzones ]
1034 1.16 kre then
1035 1.16 kre printf 'Removed zoneinfo files:\n'
1036 1.16 kre sed 's/^/ /' \
1037 1.16 kre < "${WORKDIR}"/removedzones
1038 1.16 kre fi
1039 1.16 kre printf '\nX'
1040 1.16 kre )
1041 1.16 kre MSG=${MSG%X}
1042 1.16 kre
1043 1.16 kre # Now is where the changes start happening...
1044 1.16 kre
1045 1.16 kre cd ${TZBASE}/../../../distrib/sets || exit 1
1046 1.16 kre cd lists/base || exit 2
1047 1.17 kre cvs -d "${CVSROOT}" -q update -A mi || exit 3
1048 1.17 kre cp -p mi mi.unsorted || exit 4
1049 1.16 kre sh ../../sort-list mi || exit 5
1050 1.16 kre cmp -s mi mi.unsorted ||
1051 1.16 kre DOIT cvs -d "${CVSROOT}" -q commit \
1052 1.16 kre -m 'Sort (NFCI)' mi || exit 6
1053 1.16 kre rm -f mi.unsorted
1054 1.16 kre sed -f "${WORKDIR}/sedcmds" < mi > mi.new || exit 7
1055 1.17 kre ! test -s mi.new || cmp -s mi mi.new && {
1056 1.16 kre printf 'Failed to make changes to set lists'
1057 1.16 kre exit 8
1058 1.16 kre }
1059 1.16 kre mv mi.new mi || exit 9
1060 1.16 kre sh ../../sort-list mi || exit 10
1061 1.16 kre DOIT cvs -d "${CVSROOT}" commit -m "${MSG}" mi ||
1062 1.16 kre exit 11
1063 1.16 kre printf 'Sets list successfully updated'
1064 1.16 kre exit 0
1065 1.16 kre ) || {
1066 1.16 kre printf '%s: %d\n%s %s\n' 'Sets list update failed' "$?"\
1067 1.16 kre 'Update the sets list' \
1068 1.16 kre '(src/distrib/sets/lists/base/mi) manually'
1069 1.16 kre if [ -s "${WORKDIR}"/removedzones ]
1070 1.16 kre then
1071 1.16 kre printf 'Removed Zones:'
1072 1.16 kre sed 's/^/ /' < "${WORKDIR}"/removedzones
1073 1.16 kre fi
1074 1.16 kre if [ -s "${WORKDIR}"/addedzones ]
1075 1.16 kre then
1076 1.16 kre printf 'Added Zones:'
1077 1.16 kre sed 's/^/ /' < "${WORKDIR}"/addedzones
1078 1.16 kre fi
1079 1.16 kre }
1080 1.16 kre fi
1081 1.5 apb }
1082 1.1 apb
1083 1.17 kre docupdate()
1084 1.17 kre {
1085 1.17 kre cd "${TZBASE}"
1086 1.17 kre
1087 1.17 kre MSG='CHANGES and 3RDPARTY must be updated manually'
1088 1.17 kre
1089 1.17 kre while ! [ -f UPDATING ] || ! [ -f BUILDING ]
1090 1.17 kre do
1091 1.17 kre if [ "${PWD}" = / ]
1092 1.17 kre then
1093 1.17 kre printf '%s\n' 'Unable to find NETBSDSRCDIR' "${MSG}"
1094 1.17 kre return 1
1095 1.17 kre fi
1096 1.17 kre cd ..
1097 1.17 kre done
1098 1.17 kre if ! [ -d doc ]
1099 1.17 kre then
1100 1.17 kre printf '%s\n' "No doc directory in ${PWD}" "${MSG}"
1101 1.17 kre return 1
1102 1.17 kre fi
1103 1.17 kre cd doc
1104 1.17 kre if ! [ -d CVS ]
1105 1.17 kre then
1106 1.17 kre printf '%s\n' "No CVS directory in ${PWD}" "${MSG}"
1107 1.17 kre return 1
1108 1.17 kre fi
1109 1.17 kre
1110 1.17 kre printf 'Making sure doc/CHANGES and doc/3RDPARTY are up to date\n'
1111 1.17 kre cvs -d "${CVSROOT}" -q update -A CHANGES 3RDPARTY
1112 1.17 kre
1113 1.17 kre local commit=false
1114 1.17 kre
1115 1.17 kre if grep "tzdata: Updated to ${NEWVER}" CHANGES
1116 1.17 kre then
1117 1.17 kre printf 'doc/CHANGES has already been updated'
1118 1.17 kre else
1119 1.17 kre {
1120 1.17 kre printf '\ttzdata: Updated to %s' "${NEWVER}"
1121 1.17 kre "${GLOBAL}" && printf ' (using %sgtz)' "${NEWVER}"
1122 1.17 kre date -u +" [${LOGNAME} %Y%m%d]"
1123 1.17 kre commit=true
1124 1.17 kre } >> CHANGES
1125 1.17 kre fi
1126 1.17 kre
1127 1.17 kre if grep "^Version: tzcode[^ ]* / tzdata${NEWVER}" 3RDPARTY
1128 1.17 kre then
1129 1.17 kre printf 'doc/3RDPARTY has already been updated'
1130 1.17 kre else
1131 1.17 kre # These just make the sed script below manageable.
1132 1.17 kre C=tzcode D=tzdata V=${NEWVER} T=${CVSNEWTAG}
1133 1.17 kre
1134 1.17 kre G=$V
1135 1.17 kre "${GLOBAL}" && G=${G}gtz
1136 1.17 kre
1137 1.17 kre sed < 3RDPARTY > 3RDPARTY.new \
1138 1.17 kre -e '1,/^Package: tz$/{p;d;}' \
1139 1.17 kre -e '/^Notes:/,${p;d;}' \
1140 1.17 kre -e "/^Version: /s, / ${D}.*, / ${D}${G}," \
1141 1.17 kre -e "/^Current Vers:/s,tz.*$,${C}${V} / ${D}${V}," && {
1142 1.17 kre
1143 1.17 kre mv 3RDPARTY.new 3RDPARTY
1144 1.17 kre commit=true
1145 1.17 kre }
1146 1.17 kre fi
1147 1.17 kre
1148 1.17 kre if "${commit}"
1149 1.17 kre then
1150 1.17 kre printf 'These are the changes that will be made:\n\n'
1151 1.17 kre
1152 1.17 kre cvs -d "${CVSROOT}" diff -u CHANGES 3RDPARTY || : # Ugh -e!
1153 1.17 kre
1154 1.17 kre read -p $'\nAre those OK? [y/n] ' reply
1155 1.17 kre
1156 1.17 kre MSG="Note tzdata${NEWVER} update"
1157 1.17 kre if "${GLOBAL}"
1158 1.17 kre then
1159 1.17 kre MSG="${MSG} (via ${NEWVER}gtz)"
1160 1.17 kre fi
1161 1.17 kre case "${reply}" in
1162 1.17 kre ([Yy]*) DOIT cvs -d "${CVSROOT}" commit -m "${MSG}" \
1163 1.17 kre CHANGES 3RDPARTY
1164 1.17 kre ;;
1165 1.17 kre (*) printf '%s\n' \
1166 1.17 kre 'OK, correct and commit those files manually' \
1167 1.17 kre 'The changes shown above have been made to the files'
1168 1.17 kre ;;
1169 1.17 kre esac
1170 1.17 kre fi
1171 1.17 kre return 0
1172 1.17 kre }
1173 1.17 kre
1174 1.1 apb extra()
1175 1.1 apb {
1176 1.1 apb cat <<EOF
1177 1.1 apb Also do the following:
1178 1.1 apb * Submit pullup requests for all active release branches.
1179 1.12 kre * rm -rf ${WORK_PFX} (optional)
1180 1.12 kre * Verify that
1181 1.12 kre ${UPDATE_FROM}
1182 1.12 kre * no longer exists.
1183 1.17 kre
1184 1.17 kre And if necessary (if not already done by the script):
1185 1.17 kre * Edit and commit src/doc/3RDPARTY
1186 1.17 kre * Edit and commit src/doc/CHANGES
1187 1.17 kre * Edit and commit src/distrib/sets/lists/base/mi
1188 1.1 apb EOF
1189 1.17 kre
1190 1.17 kre rm -f "${UPDATE_FROM}" # just to try to make sure, as we're done!
1191 1.1 apb }
1192 1.1 apb
1193 1.1 apb main()
1194 1.1 apb {
1195 1.1 apb set -e
1196 1.12 kre validate_pwd
1197 1.1 apb findcvsroot
1198 1.12 kre mkworkpfx
1199 1.16 kre
1200 1.12 kre argparse "$@"
1201 1.16 kre
1202 1.16 kre cvsupdate || fail 'working directory (dist) cvs update failed:'" $?"
1203 1.16 kre
1204 1.12 kre setup_versions
1205 1.1 apb mkworkdir
1206 1.1 apb fetch
1207 1.17 kre "${GLOBAL}" || checksig
1208 1.1 apb extract
1209 1.16 kre
1210 1.16 kre zonelists
1211 1.16 kre
1212 1.2 apb addnews
1213 1.1 apb trimnews
1214 1.1 apb mkimportmsg
1215 1.1 apb editimportmsg
1216 1.1 apb cvsimport
1217 1.1 apb cvsmerge
1218 1.1 apb resolveconflicts
1219 1.17 kre checkfilecontents
1220 1.1 apb cvscommitmerge
1221 1.16 kre updatedzones
1222 1.16 kre
1223 1.16 kre setlistupdate
1224 1.16 kre
1225 1.12 kre rm -f "${UPDATE_FROM}"
1226 1.16 kre rm -fr "${WORK_PFX}"/oldzones \
1227 1.16 kre "${WORK_PFX}"/newzones \
1228 1.16 kre "${WORK_PFX}"/updzones
1229 1.17 kre
1230 1.17 kre docupdate
1231 1.1 apb extra
1232 1.1 apb }
1233 1.1 apb
1234 1.1 apb main "$@"
1235