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