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