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