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