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