yann@1822: #!/bin/bash yann@1822: #set -x yann@1822: yann@1837: export LC_ALL=C yann@1837: yann@1822: my_name="$( basename "${0}" )" yann@1822: yann@1822: usage() { yann@1822: cat <<-_EOF_ yann@1822: Usage: yann@1822: ${my_name} yann@1822: _EOF_ yann@1822: } yann@1822: yann@1822: repos="${1}" yann@1822: version="${2}" yann@1822: yann@1822: [ -n "${repos}" ] || { usage; exit 1; } yann@1822: [ -d "${repos}" ] || { printf "${my_name}: ${repos}: no such file or directory\n"; exit 1; } yann@1822: [ -n "${version}" ] || { usage; exit 1; } yann@1822: yann@2857: _hg() { yann@2857: HGPLAIN=1 hg --config progress.disabled=true "$@" yann@2857: } yann@2857: yann@1822: gen_bound_revs() { yann@2857: r1=$( _hg log \ yann@1822: |awk 'BEGIN { yann@1822: found=0; yann@1822: } yann@1822: $1=="'"${label}"':" { yann@1822: split($2,a,":"); rev=a[1]; yann@1822: } yann@1822: $0~/^summary:[[:space:]]*[[:digit:]]+\.[[:digit:]]+: '"${msg}"'/ \ yann@1822: && found==0 { yann@1822: printf( "%d\n", rev ); found=1; yann@1822: }' yann@1822: ) yann@1822: yann@2857: r2=$( _hg log -b "${branch}" \ yann@1822: |awk '$1=="changeset:" { yann@1822: split($2,a,":"); yann@1822: printf( "%d\n", a[1] ); yann@1822: nextfile; yann@1822: }' yann@1822: ) yann@1822: yann@1822: r1_log=$((r1+log_offset)) yann@1822: if [ ${#r1_log} -gt ${#r2} ]; then yann@1822: rev_w=${#r1_log} yann@1822: else yann@1822: rev_w=${#r2} yann@1822: fi yann@1822: } yann@1822: yann@1822: print_intro_mail() { yann@1822: cat <<-_EOF_ yann@1822: Hello all! yann@1822: yann@1822: I'm pleased to announce the release of crosstool-NG ${version}! yann@1822: yann@1822: As usual, there has been quite a number of improvements, new features, yann@1822: and bug fixes all around. The most notable changes are listed below: yann@1822: yann@1822: YEM: yann@1822: YEM: PUT YOUR MESSAGE HERE yann@1822: YEM: yann@1822: yann@1822: This marks the beginning of the ${ver_M}.${ver_m} maintenance branch, and the end of yann@1822: the previous maintenance branch. As always, comments and suggestions yann@1822: are most welcome! yann@1822: yann@1822: The release can be found at the following URLs: yann@2725: Changelog: http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-${version}.changelog yann@2725: Tarball: http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-${version}.tar.bz2 yann@2725: Patches: http://crosstool-ng.org/download/crosstool-ng/01-fixes/${version}/ yann@1822: yann@1822: As a reminder, the home for crosstool-NG is: yann@2725: http://crosstool-ng.org/ yann@1822: yann@1822: Crosstool-NG also has a Freshmeat page: yann@1833: http://freshmeat.net/projects/crosstool-ng yann@1822: _EOF_ yann@1822: } yann@1822: yann@1822: print_intro_changelog_full_release() { yann@1822: cat <<-_EOF_ yann@1822: crosstool-NG ${version} -- ${date} yann@1822: yann@1822: This is a feature-release. Significant changes are: yann@1822: yann@1822: YEM: yann@1822: YEM: PUT YOUR MESSAGE HERE yann@1822: YEM: yann@1822: _EOF_ yann@1822: } yann@1822: yann@1822: print_intro_changelog_bug_fix() { yann@1822: cat <<-_EOF_ yann@1822: crosstool-NG ${version} -- ${date} yann@1822: yann@1822: This is a bug-fix-only release. yann@1822: _EOF_ yann@1822: } yann@1822: yann@1822: print_author_stats() { yann@1822: printf "\nMany thanks to the people who contributed to this release:\n\n" yann@1822: prev_author="" yann@1822: template='{author|person}\n' yann@2857: _hg log -b "${branch}" -r "${r1_log}:${r2}" \ yann@1822: --template "${template}" \ yann@1822: |sed -r -e 's/"//g;' \ yann@1822: |awk -F '' '{ yann@1822: nb[$0]++; yann@1822: } yann@1822: END { yann@1822: for( author in nb ) { yann@1822: printf( " %4d %s\n", nb[author], author ); yann@1822: } yann@1822: }' \ yann@1943: |sort -s -k1nr -k2 yann@1822: } yann@1822: yann@1822: print_author_shortlog() { yann@1822: printf "\nHere is the per-author shortlog:\n" yann@1822: prev_author="" yann@1822: template='{author|person}|{rev}|{branches}|{desc|firstline}\n' yann@2857: _hg log -b "${branch}" -r "${r1_log}:${r2}" \ yann@1822: --template "${template}" \ yann@1822: |awk -F '' '{ yann@1822: n=split( $0,a,"|" ); yann@1822: printf( "%s", gensub("\"","","g",a[1]) ); yann@1822: printf( "|%0*d", '${rev_w}', a[2] ); yann@1822: for(i=3;i<=n;i++) { yann@1822: printf( "|%s", a[i] ); yann@1822: } yann@1822: printf( "\n" ); yann@1822: }' \ yann@1822: |sort \ yann@1822: |while read line; do yann@1822: author="$( echo "${line}" |cut -d \| -f 1 )" yann@1822: rev="$( echo "${line}" |cut -d \| -f 2 )" yann@1822: br="$( echo "${line}" |cut -d \| -f 3 )" yann@1822: desc="$( echo "${line}" |cut -d \| -f 4- )" yann@1822: yann@1822: case "${br}" in yann@1822: ${branch}) ;; yann@1822: [0-9]*.*) continue;; yann@1822: *) ;; yann@1822: esac yann@1822: yann@1822: case "${desc}" in yann@1822: Merge.) continue;; yann@1822: *": close "*" branch"*) continue;; yann@1822: # *\(merged\)) continue;; yann@1822: esac yann@1822: yann@1822: author="$( echo "${author}" |sed -r -e 's/"//g;' )" yann@1822: yann@1822: if [ ! "${prev_author}" = "${author}" ]; then yann@1822: printf "\n" yann@1822: printf " ${author}:\n" yann@1822: prev_author="${author}" yann@1822: fi yann@1822: rev="$( echo "${rev}" |sed -r -e 's/^0*//;' )" yann@1822: yann@1822: printf "%s\n" "${desc}" \ yann@1822: |fmt -w 65 \ yann@1822: |(first=1; while read l; do yann@1822: if [ -n "${first}" ]; then yann@1822: printf " [%*d] %s\n" ${rev_w} ${rev} "${l}" yann@1822: first= yann@1822: else yann@1822: printf " %*.*s %s\n" ${rev_w} ${rev_w} '' "${l}" yann@1822: fi yann@1822: done) yann@1822: done yann@1822: } yann@1822: yann@1822: print_diffstat() { yann@1822: printf "\nThe diffstat follows:\n\n" yann@2857: _hg diff -r "${r1}:${r2}" --color=never \ yann@1822: |diffstat -r 2 -p 1 -w 10 \ yann@1822: |tail -n 1 \ yann@1822: |sed -r -e 's/^ */ /;' yann@1822: yann@2857: _hg diff -r "${r1}:${r2}" --color=never \ yann@1822: |diffstat -f 1 -r 2 -p 1 -w 10 \ yann@1822: |head -n -1 \ yann@1822: |while read file line; do yann@1822: if [ ${#file} -gt 57 ]; then yann@1833: file="$( echo "${file}" |sed -r -e 's/^(.{,24}).*(.{28})$/\1.....\2/;' )" yann@1822: fi yann@1822: printf " %-57s %s\n" "${file}" "${line}" yann@1822: done yann@1822: } yann@1822: yann@1833: print_short_diffstat() { yann@1833: printf "\nThe short diffstat follows:\n\n" yann@1833: yann@1833: eval total=$(( $( yann@2857: _hg diff -r "${r1}:${r2}" --color=never "${i}" \ yann@1833: |diffstat -r 2 -p 1 -w 10 \ yann@1833: |tail -n 1 \ yann@1833: |sed -r -e 's/^[[:space:]]*[[:digit:]]+ files? changed(,[[:space:]]+|$)//;' \ yann@1833: -e 's/([[:digit:]]+)[^-\+]+\((-|\+)\)/\1/g;' \ yann@1833: -e 's/,//g; s/ /+/; s/^$/0/;' yann@1833: ) )) yann@1833: printf " %-24.24s %5d(+/-)\n" "Total" ${total} yann@1833: others=${total} yann@1833: yann@1833: { for i in \ yann@1833: kconfig/ \ yann@1833: patches/ \ yann@1833: config/*/ \ yann@1833: scripts/build/*/ \ yann@1833: samples/ \ yann@1833: ; do yann@1833: eval val=$(( $( yann@2857: _hg diff -r "${r1}:${r2}" --color=never "${i}" \ yann@1833: |diffstat -r 2 -p 1 -w 10 \ yann@1833: |tail -n 1 \ yann@1833: |sed -r -e 's/^[[:space:]]*[[:digit:]]+ files? changed(,[[:space:]]+|$)//;' \ yann@1833: -e 's/([[:digit:]]+)[^-\+]+\((-|\+)\)/\1/g;' \ yann@1833: -e 's/,//g; s/ /+/; s/^$/0/;' yann@1833: ) )) yann@1833: if [ ${val} -gt $((total/100)) ]; then yann@1833: printf "%d %s\n" $(((1000*val)/total)) "${i}" yann@1833: others=$((others-val)) yann@1833: fi yann@1833: done; printf "%d Others\n" $(((1000*others)/total)); } \ yann@1833: |sort -nr \ yann@1833: |{ while read v i; do yann@1833: if [ "${i}" = "Others" ]; then yann@1833: others=${v} yann@1833: else yann@1833: printf " %-24.24s %3d.%d%%\n" "${i}" $((v/10)) $((v%10)) yann@1833: fi yann@1833: done; printf " %-24.24s %3d.%d%%\n" "Others" $((others/10)) $((others%10)); } yann@1833: } yann@1833: yann@1822: ver_M="$( printf "${version}" |cut -d . -f 1 )" yann@1822: ver_m="$( printf "${version}" |cut -d . -f 2 )" yann@1822: ver_p="$( printf "${version}" |cut -d . -f 3 )" yann@1822: yann@2978: sob_line="$( printf "Signed-off-by: "; _hg debugconfig ui.username )" yann@1822: prefix="$(pwd)/crosstool-ng-${version}" yann@1822: pushd "${repos}" >/dev/null 2>&1 yann@1822: yann@1822: printf "Checking for existing tag: " yann@2857: if _hg tags |grep -E '^'"crosstool-ng-${version}"'\>' >/dev/null; then yann@1822: printf "already tagged\n" yann@1822: exit 1 yann@1822: fi yann@1822: printf "no\n" yann@1822: yann@1822: if [ ${ver_p} -eq 0 ]; then yann@1822: print_mail="yes" yann@1822: print_intro_changelog="print_intro_changelog_full_release" yann@1822: label="parent" yann@1822: msg="create maintenance branch, (update|bump) version to [[:digit:]]+"'\'".[[:digit:]]+"'\'".0"'$' yann@1822: branch="default" yann@1822: log_offset=0 yann@1822: else yann@1822: print_mail="no" yann@1822: print_intro_changelog="print_intro_changelog_bug_fix" yann@1822: label="changeset" yann@1822: msg="(update|bump) version to ${ver_M}"'\'".${ver_m}"'\'".$((ver_p-1))"'\+hg$' yann@1822: branch="${ver_M}.${ver_m}" yann@1822: log_offset=1 yann@1822: fi yann@1822: yann@1822: printf "Computing boundary revisions:" yann@1822: gen_bound_revs yann@1822: printf " %d:%d\n" ${r1} ${r2} yann@1822: yann@1822: printf "Tagging release:" yann@2857: _hg up "${branch}" >/dev/null yann@1822: if [ ${ver_p} -eq 0 ]; then yann@1822: printf " update version" yann@2857: _hg branch "${ver_M}.${ver_m}" >/dev/null yann@1822: echo "${version}" >".version" yann@2978: _msg="$( printf "%s.%s: create maintenance branch, update version to %s\n\n%s" \ yann@2978: "${ver_M}" "${ver_m}" "${version}" "${sob_line}" yann@2978: )" yann@2978: _hg ci -m "${_msg}" yann@1822: else yann@1822: printf " update version" yann@1822: echo "${version}" >".version" yann@2978: _msg="$( printf "%s.%s: update version to %s\n\n%s" \ yann@2978: "${ver_M}" "${ver_m}" "${version}" "${sob_line}" yann@2978: )" yann@2978: _hg ci -m "${_msg}" yann@1822: fi yann@1822: yann@1822: printf ", tag" yann@2978: _msg="$( printf "Tagging release %s\n\n%s" "${version}" "${sob_line}" )" yann@2978: _hg tag -m "${_msg}" crosstool-ng-${version} yann@1822: yann@1822: printf ", update version" yann@1822: echo "${version}+hg" >".version" yann@2978: _msg="$( printf "%s.%s: update version to %s+hg\n\n%s" \ yann@2978: "${ver_M}" "${ver_m}" "${version}" "${sob_line}" yann@2978: )" yann@2978: _hg ci -m "${_msg}" yann@1822: yann@1822: printf ", date" yann@2857: date="$( _hg log -r crosstool-ng-${version} --template '{date|isodate}\n' \ yann@1822: |sed -r -e 's/-|://g; s/ /./; s/ //;' \ yann@1822: )" yann@1822: printf ", done.\n" yann@1822: yann@1822: if [ ${ver_p} -eq 0 ]; then yann@1822: printf "Generating release mail:" yann@1822: printf " intro" yann@1822: print_intro_mail > "${prefix}.mail" yann@1822: printf ", stats" yann@1822: print_author_stats >>"${prefix}.mail" yann@1822: printf ", shortlog" yann@1822: print_author_shortlog >>"${prefix}.mail" yann@1833: printf ", diffstat" yann@1833: print_short_diffstat >>"${prefix}.mail" yann@1822: printf ", done.\n" yann@1822: fi yann@1822: yann@1822: printf "Generating release changelog:" yann@1822: printf " intro" yann@1822: ${print_intro_changelog} > "${prefix}.changelog" yann@1822: printf ", stats" yann@1822: print_author_stats >>"${prefix}.changelog" yann@1822: printf ", shortlog" yann@1822: print_author_shortlog >>"${prefix}.changelog" yann@1822: printf ", diffstat" yann@1822: print_diffstat >>"${prefix}.changelog" yann@1822: printf ", done.\n" yann@1822: yann@1822: popd >/dev/null 2>&1 yann@1822: yann@1822: printf "Creating tarball:" yann@1822: prefix="crosstool-ng-${version}" yann@2858: printf " extract" yann@2857: date="$( _hg log -R "${repos}" -r "${prefix}" --template '{date|rfc822date}\n' )" yann@2858: tmpdir="$( mktemp -d --tmpdir XXXXXX )" yann@2858: _hg archive --cwd "${repos}" -r "${prefix}" -X '.hg*' --type files "${tmpdir}/${prefix}" yann@2858: printf ", bootstrap" yann@2858: pushd "${tmpdir}/${prefix}" >/dev/null 2>&1 yann@2858: ./bootstrap >/dev/null yann@2859: rm -rf autom4te.cache yann@2858: popd >/dev/null 2>&1 yann@2858: printf ", tarball" yann@2859: tar cjf "$(pwd)/${prefix}.tar.bz2" -C "${tmpdir}" "${prefix}" yann@2858: rm -rf "${tmpdir}" yann@1822: printf ", sum" yann@1822: for s in md5 sha1 sha512; do yann@1822: ${s}sum "${prefix}.tar.bz2" >"${prefix}.tar.bz2.${s}" yann@1822: done yann@1822: printf ", touch" yann@1822: touch -d "${date}" "${prefix}"* yann@1822: printf ", done.\n" yann@1822: yann@1822: if [ ${ver_p} -eq 0 ]; then yann@1822: printf "\nAn editor will be launched for you to edit the mail.\n" yann@1822: read -p "Press enter when ready..." foo yann@1833: cp "${prefix}.mail"{,.orig} yann@1822: vi "${prefix}.mail" yann@1833: diff -du -U 1 "${prefix}.mail"{.orig,} |patch -p0 "${prefix}.changelog" >/dev/null yann@1833: rm -f "${prefix}".{mail,changelog}.orig yann@1822: fi yann@1822: yann@1822: printf "\nAn editor will be launched for you to review the changelog.\n" yann@1822: read -p "Press enter when ready..." foo yann@1822: vi "${prefix}.changelog" yann@1822: yann@1822: printf "\nNow, you can push the changes with: hg push -R '${repos}'\n"