scripts/mk-release.sh
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Sun Mar 07 13:17:27 2010 +0100 (2010-03-07)
changeset 1822 7893174d0fe8
child 1833 a4c371728d07
permissions -rwxr-xr-x
scripts: add script to make a release
     1 #!/bin/bash
     2 #set -x
     3 
     4 my_name="$( basename "${0}" )"
     5 
     6 usage() {
     7     cat <<-_EOF_
     8 		Usage:
     9 		    ${my_name} <repos_dir> <M.m.p>
    10 	_EOF_
    11 }
    12 
    13 repos="${1}"
    14 version="${2}"
    15 
    16 [ -n "${repos}"   ] || { usage; exit 1; }
    17 [ -d "${repos}"   ] || { printf "${my_name}: ${repos}: no such file or directory\n"; exit 1; }
    18 [ -n "${version}" ] || { usage; exit 1; }
    19 
    20 gen_bound_revs() {
    21     r1=$( hg log    \
    22           |awk 'BEGIN {
    23                   found=0;
    24                 }
    25                 $1=="'"${label}"':" {
    26                   split($2,a,":"); rev=a[1];
    27                 }
    28                 $0~/^summary:[[:space:]]*[[:digit:]]+\.[[:digit:]]+: '"${msg}"'/ \
    29                 && found==0 {
    30                   printf( "%d\n", rev ); found=1;
    31                 }'
    32         )
    33 
    34     r2=$( hg log -b "${branch}" \
    35           |awk '$1=="changeset:" {
    36                   split($2,a,":");
    37                   printf( "%d\n", a[1] );
    38                   nextfile;
    39                 }'
    40         )
    41 
    42     r1_log=$((r1+log_offset))
    43     if [ ${#r1_log} -gt ${#r2} ]; then
    44         rev_w=${#r1_log}
    45     else
    46         rev_w=${#r2}
    47     fi
    48 }
    49 
    50 print_intro_mail() {
    51     cat <<-_EOF_
    52 		Hello all!
    53 		
    54 		I'm pleased to announce the release of crosstool-NG ${version}!
    55 		
    56 		As usual, there has been quite a number of improvements, new features,
    57 		and bug fixes all around. The most notable changes are listed below:
    58 		
    59 		YEM:
    60 		YEM: PUT YOUR MESSAGE HERE
    61 		YEM:
    62 		
    63 		This marks the beginning of the ${ver_M}.${ver_m} maintenance branch, and the end of
    64 		the previous maintenance branch. As always, comments and suggestions
    65 		are most welcome!
    66 		
    67 		The release can be found at the following URLs:
    68 		Changelog: http://ymorin.is-a-geek.org/download/crosstool-ng/crosstool-ng-${version}.changelog
    69 		Tarball:   http://ymorin.is-a-geek.org/download/crosstool-ng/crosstool-ng-${version}.tar.bz2
    70 		Patches:   http://ymorin.is-a-geek.org/download/crosstool-ng/01-fixes/${version}
    71 		
    72 		As a reminder, the home for crosstool-NG is:
    73 		http://ymorin.is-a-geek.org/projects/crosstool
    74 		
    75 		Crosstool-NG also has a Freshmeat page:
    76 		http://freshmeat.net/projects/crosstool-ng/
    77 	_EOF_
    78 }
    79 
    80 print_intro_changelog_full_release() {
    81     cat <<-_EOF_
    82 		crosstool-NG ${version} -- ${date}
    83 		
    84 		This is a feature-release. Significant changes are:
    85 		
    86 		YEM:
    87 		YEM: PUT YOUR MESSAGE HERE
    88 		YEM:
    89 	_EOF_
    90 }
    91 
    92 print_intro_changelog_bug_fix() {
    93     cat <<-_EOF_
    94 		crosstool-NG ${version} -- ${date}
    95 		
    96 		This is a bug-fix-only release.
    97 	_EOF_
    98 }
    99 
   100 print_author_stats() {
   101     printf "\nMany thanks to the people who contributed to this release:\n\n"
   102     prev_author=""
   103     template='{author|person}\n'
   104     hg log -b "${branch}" -r "${r1_log}:${r2}"                  \
   105            --template "${template}"                             \
   106     |sed -r -e 's/"//g;'                                        \
   107     |awk -F '' '{
   108                   nb[$0]++;
   109                 }
   110                 END {
   111                   for( author in nb ) {
   112                     printf( "   %4d  %s\n", nb[author], author );
   113                   }
   114                 }'                                              \
   115     |sort -rn
   116 }
   117 
   118 print_author_shortlog() {
   119     printf "\nHere is the per-author shortlog:\n"
   120     prev_author=""
   121     template='{author|person}|{rev}|{branches}|{desc|firstline}\n'
   122     hg log -b "${branch}" -r "${r1_log}:${r2}"              \
   123            --template "${template}"                         \
   124     |awk -F '' '{
   125                   n=split( $0,a,"|" );
   126                   printf( "%s", gensub("\"","","g",a[1]) );
   127                   printf( "|%0*d", '${rev_w}', a[2] );
   128                   for(i=3;i<=n;i++) {
   129                     printf( "|%s", a[i] );
   130                   }
   131                   printf( "\n" );
   132                 }'                                          \
   133     |sort                                                   \
   134     |while read line; do
   135         author="$( echo "${line}" |cut -d \| -f 1 )"
   136         rev="$( echo "${line}" |cut -d \| -f 2 )"
   137         br="$( echo "${line}" |cut -d \| -f 3 )"
   138         desc="$( echo "${line}" |cut -d \| -f 4- )"
   139 
   140         case "${br}" in
   141             ${branch})  ;;
   142             [0-9]*.*)    continue;;
   143             *) ;;
   144         esac
   145 
   146         case "${desc}" in
   147             Merge.)                 continue;;
   148             *": close "*" branch"*) continue;;
   149 #           *\(merged\))            continue;;
   150         esac
   151 
   152         author="$( echo "${author}" |sed -r -e 's/"//g;' )"
   153 
   154         if [ ! "${prev_author}" = "${author}" ]; then
   155             printf "\n"
   156             printf "    ${author}:\n"
   157             prev_author="${author}"
   158         fi
   159         rev="$( echo "${rev}" |sed -r -e 's/^0*//;' )"
   160 
   161         printf "%s\n" "${desc}"     \
   162         |fmt -w 65                  \
   163         |(first=1; while read l; do
   164             if [ -n "${first}" ]; then
   165                 printf "        [%*d] %s\n" ${rev_w} ${rev} "${l}"
   166                 first=
   167             else
   168                 printf "         %*.*s  %s\n" ${rev_w} ${rev_w} '' "${l}"
   169             fi
   170         done)
   171     done
   172 }
   173 
   174 print_diffstat() {
   175     printf "\nThe diffstat follows:\n\n"
   176     hg diff -r "${r1}:${r2}" --color=never  \
   177     |diffstat -r 2 -p 1 -w 10               \
   178     |tail -n 1                              \
   179     |sed -r -e 's/^ */    /;'
   180 
   181     hg diff -r "${r1}:${r2}" --color=never  \
   182     |diffstat -f 1 -r 2 -p 1 -w 10          \
   183     |head -n -1                             \
   184     |while read file line; do
   185         if [ ${#file} -gt 57 ]; then
   186             file="...$( echo "${file}" |sed -r -e 's/^.*(.{54})$/\1/;' )"
   187         fi
   188         printf "    %-57s %s\n" "${file}" "${line}"
   189     done
   190 }
   191 
   192 ver_M="$( printf "${version}" |cut -d . -f 1 )"
   193 ver_m="$( printf "${version}" |cut -d . -f 2 )"
   194 ver_p="$( printf "${version}" |cut -d . -f 3 )"
   195 
   196 prefix="$(pwd)/crosstool-ng-${version}"
   197 pushd "${repos}" >/dev/null 2>&1
   198 
   199 printf "Checking for existing tag: "
   200 if hg tags |grep -E '^'"crosstool-ng-${version}"'\>' >/dev/null; then
   201     printf "already tagged\n"
   202     exit 1
   203 fi
   204 printf "no\n"
   205 
   206 if [ ${ver_p} -eq 0 ]; then
   207     print_mail="yes"
   208     print_intro_changelog="print_intro_changelog_full_release"
   209     label="parent"
   210     msg="create maintenance branch, (update|bump) version to [[:digit:]]+"'\'".[[:digit:]]+"'\'".0"'$'
   211     branch="default"
   212     log_offset=0
   213 else
   214     print_mail="no"
   215     print_intro_changelog="print_intro_changelog_bug_fix"
   216     label="changeset"
   217     msg="(update|bump) version to ${ver_M}"'\'".${ver_m}"'\'".$((ver_p-1))"'\+hg$'
   218     branch="${ver_M}.${ver_m}"
   219     log_offset=1
   220 fi
   221 
   222 printf "Computing boundary revisions:"
   223 gen_bound_revs
   224 printf " %d:%d\n" ${r1} ${r2}
   225 
   226 printf "Tagging release:"
   227 hg up "${branch}" >/dev/null
   228 if [ ${ver_p} -eq 0 ]; then
   229     printf " update version"
   230     hg branch "${ver_M}.${ver_m}" >/dev/null
   231     echo "${version}" >".version"
   232     hg ci -m "${ver_M}.${ver_m}: create maintenance branch, update version to ${version}"
   233 else
   234     printf " update version"
   235     echo "${version}" >".version"
   236     hg ci -m "${ver_M}.${ver_m}: update version to ${version}"
   237 fi
   238 
   239 printf ", tag"
   240 hg tag -m "Tagging release ${version}" crosstool-ng-${version}
   241 
   242 printf ", update version"
   243 echo "${version}+hg" >".version"
   244 hg ci -m "${ver_M}.${ver_m}: update version to ${version}+hg"
   245 
   246 printf ", date"
   247 date="$( hg log -r crosstool-ng-${version} --template '{date|isodate}\n'    \
   248          |sed -r -e 's/-|://g; s/ /./; s/ //;'                              \
   249        )"
   250 printf ", done.\n"
   251 
   252 if [ ${ver_p} -eq 0 ]; then
   253     printf "Generating release mail:"
   254     printf " intro"
   255     print_intro_mail        > "${prefix}.mail"
   256     printf ", stats"
   257     print_author_stats      >>"${prefix}.mail"
   258     printf ", shortlog"
   259     print_author_shortlog   >>"${prefix}.mail"
   260     printf ", done.\n"
   261 fi
   262 
   263 printf "Generating release changelog:"
   264 printf " intro"
   265 ${print_intro_changelog}    > "${prefix}.changelog"
   266 printf ", stats"
   267 print_author_stats          >>"${prefix}.changelog"
   268 printf ", shortlog"
   269 print_author_shortlog       >>"${prefix}.changelog"
   270 printf ", diffstat"
   271 print_diffstat              >>"${prefix}.changelog"
   272 printf ", done.\n"
   273 
   274 popd >/dev/null 2>&1
   275 
   276 printf "Creating tarball:"
   277 prefix="crosstool-ng-${version}"
   278 printf " cloning"
   279 hg clone "${repos}" "${prefix}" >/dev/null
   280 hg up -R "${prefix}" "${prefix}" >/dev/null
   281 date="$( hg log -R "${prefix}" -r "${prefix}" --template '{date|rfc822date}\n' )"
   282 printf ", purging"
   283 rm -rf "${prefix}/"{.hg,.hgtags,.hgignore}
   284 printf ", tarball"
   285 tar cjf "${prefix}.tar.bz2" "${prefix}"
   286 printf ", sum"
   287 for s in md5 sha1 sha512; do
   288     ${s}sum "${prefix}.tar.bz2" >"${prefix}.tar.bz2.${s}"
   289 done
   290 printf ", cleaning"
   291 rm -rf "${prefix}"
   292 printf ", touch"
   293 touch -d "${date}" "${prefix}"*
   294 printf ", done.\n"
   295 
   296 if [ ${ver_p} -eq 0 ]; then
   297     printf "\nAn editor will be launched for you to edit the mail.\n"
   298     read -p "Press enter when ready..." foo
   299 	cp "${prefix}.mail"{,.orig}
   300     vi "${prefix}.mail"
   301 	diff -du -U 1 "${prefix}.mail"{.orig,} |patch -p0 "${prefix}.changelog" >/dev/null
   302 fi
   303 
   304 printf "\nAn editor will be launched for you to review the changelog.\n"
   305 read -p "Press enter when ready..." foo
   306 vi "${prefix}.changelog"
   307 
   308 printf "\nNow, you can push the changes with:   hg push -R '${repos}'\n"