From a263ebcdc2511f8b29300fae9a6be9904b3ce96e Mon Sep 17 00:00:00 2001 From: sigoure Date: Tue, 24 Oct 2006 09:48:34 +0000 Subject: [PATCH] Handle multiple ChangeLogs. Many sanity fixes. Don't svn up before committing: it's useless. Instead, find the next revision number by querying the repository (not slower but safer: it doesn't modify files before committing). --- svn-wrapper.sh | 166 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 130 insertions(+), 36 deletions(-) diff --git a/svn-wrapper.sh b/svn-wrapper.sh index 68df96e..b6e319c 100755 --- a/svn-wrapper.sh +++ b/svn-wrapper.sh @@ -158,11 +158,11 @@ You might consider using \`export $1 \`" # get_unique_file_name file-name get_unique_file_name() { - test -f "$1" || { + test -e "$1" || { echo "$1" && return 0 } gufn="$1"; i=1 - while test -f "$gufn.$i"; do + while test -e "$gufn.$i"; do i=`expr $i + 1` done echo "$gufn.$i" @@ -264,34 +264,129 @@ How can I download any update without them?' # ------------------------------- # # svn_commit [args...] +# Here is how the commit process goes: +# First we look in the arguments passed to commit: +# If there are some files or paths, the user wants to commit these only. In +# this case, we must search for ChangeLogs from these paths. We might find +# more than one ChangeLog, in this case the user will be prompted to pick up +# one. +# Otherwise (no path passed in the command line) the user just wants to +# commit the current working directory. +# In any case, we schedule "ChangeLog" for commit. +# Alright now that we know which ChangeLog to use, we look in the ChangeLog's +# directory if there is a ",svn-log" file which would mean that a previous +# commit didn't finish successfully. If there is such a file, the user is +# prompted to know whether they want to resume that commit or simply start a +# new one. +# When the user wants to resume a commit, the ",svn-log" file is loaded and we +# retrieve the value of "$@" that was saved in the file. +# Otherwise we build a template ChangeLog entry. +# Then we open the template ChangeLog entry with $EDITOR so that the user +# fills it properly. +# Finally, we commit. svn_commit() { - # -------------- # - # Find ChangeLog # - # -------------- # - - here=`pwd`; found=0; change_log_files='' - while [ $found -eq 0 ]; do - if [ -f ./ChangeLog ]; then - found=1 - else - cd .. - fi - change_log_dir=`pwd -P` - # Stop searching when in / ... hmz :P - test x"$change_log_dir" = x/ && { - if yesno 'svn-wrapper: Error: Cannot find a ChangeLog file! -You might want to create an empty one (eg: `touch ChangeLog` where appropriate) -Do you want to proceed without using a ChangeLog?'; then - cd "$here" - $SVN commit "$@" && $SVN update - return $? + here=`pwd` + + # Check if the user passed some paths to commit explicitly + # because in this case we must add the ChangeLog to the commit and search + # the ChangeLog from the dirname of that file. + i=0; search_from=''; add_changelog=no + while [ $i -lt $# ]; do + arg="$1" + # If the argument is a valid path: add the ChangeLog in the list of + # files to commit + if test -e "$arg"; then + add_changelog=yes + if test -d "$arg"; then + search_from_add="$arg" else - return 1 + search_from_add=`dirname "$arg"` fi - } + search_from="$search_from:$search_from_add" + fi + shift + set dummy "$@" "$arg" + shift + i=`expr $i + 1` done - notice "using $change_log_dir/ChangeLog" + if [ $add_changelog = no ]; then + # There is no path/file in the command line: the user wants to commit the + # current directory. Make it explicit now: + set dummy "$@" '.' + shift + fi + search_from=`echo "$search_from" | sed 's/^://; s/^$/./'` + + # ----------------- # + # Find ChangeLog(s) # + # ----------------- # + + nb_chlogs=0; change_log_dirs='' + save_IFS=$IFS; IFS=':' + for dir in $search_from; do + IFS=$save_IFS + test -z "$dir" && dir='.' + # First: come back to the original place + cd "$here" || abort "Cannot cd to $here" + cd "$dir" || continue # Then: Enter $dir (which can be a relative path) + found=0 + while [ $found -eq 0 ]; do + this_chlog_dir=`pwd -P` + if [ -f ./ChangeLog ]; then + found=1 + nb_chlogs=`expr $nb_chlogs + 1` + change_log_dirs="$change_log_dirs:$this_chlog_dir" + else + cd .. + fi + # Stop searching when in / ... hmz :P + test x"$this_chlog_dir" = x/ && break + done # end while: did we find a ChangeLog + done # end for: find ChangeLogs in $search_from + change_log_dirs=`echo "$change_log_dirs" | sed 's/^://'` + + # Did we find a ChangeLog? More than one? + if [ $nb_chlogs -eq 0 ]; then + if yesno 'svn-wrapper: Error: Cannot find a ChangeLog file! +You might want to create an empty one (eg: `touch ChangeLog` where appropriate) +Do you want to proceed without using a ChangeLog?'; then + cd "$here" + $SVN commit "$@" && $SVN update + return $? + else + return 1 + fi + elif [ $nb_chlogs -gt 1 ]; then + notice "$nb_chlogs ChangeLogs were found, pick up one:" + + IFS=':'; i=0 + for a_chlog_dir in $change_log_dirs; do + i=`expr $i + 1` + echo "$i. $a_chlog_dir/ChangeLog" + done + echo -n "Which ChangeLog do you want to use? [1-$i] " + read chlog_no || abort "Cannot read answer on stdin." + + case "$chlog_no" in + *[^0-9]*) abort "Invalid ChangeLog number: $chlog_no" + esac + test "$chlog_no" -le $i || abort "Invalid ChangeLog number: $chlog_no +max value was: $i" + test "$chlog_no" -ge 1 || abort "Invalid ChangeLog number: $chlog_no +min value was: 1" + change_log_dir=`echo "$change_log_dirs" | tr ':' '\n' | sed "${chlog_no}!d"` + else # Only one ChangeLog found + change_log_dir=$change_log_dirs + notice "using $change_log_dir/ChangeLog" + fi + + test -f "$change_log_dir/ChangeLog" \ + || abort "No such file or directory: $change_log_dir/ChangeLog" + + # Now we can safely schedule the ChangeLog for the commit. + set dummy "$@" "$change_log_dir/ChangeLog" + shift # Warn for files that are not added in the repos. conflicts=`$SVN status | sed '/^\?......[^,+]/!d'` @@ -308,12 +403,16 @@ any of the following files before committing:" and/or missing files (\`!'): $conflicts" - $SVN update || abort 'svn update failed.' + repos_root=`$SVN info | sed '/^Repository Root/!d;s/^Repository Root: //'` + # It looks like svn <1.3 didn't display a "Repository Root" entry. + test x"$repos_root" = x && \ + repos_root=`$SVN info | sed '/^URL/!d;s/^URL: //'` + cd "$here" YYYY=`date '+%Y'` MM=`date '+%m'` DD=`date '+%d'` - REV=`$SVN info | sed '/^Revision: /!d;s///'` + REV=`$SVN info "$repos_root" | sed '/^Revision: /!d;s///'` test x"$REV" = x && REV=`$SVN info | sed '/^Last Changed Rev: /!d;s///'` test x"$REV" = x && warn 'Cannot detect the current revision.' REV=`expr $REV + 1` @@ -354,12 +453,6 @@ they have been replaced by these: $saved_args" # Gather info for the template message # # ------------------------------------ # - repos_root=`$SVN info | sed '/^Repository Root/!d;s/^Repository Root: //'` - # It looks like svn <1.3 didn't display a "Repository Root" entry. - test x"$repos_root" = x && \ - repos_root=`$SVN info | sed '/^URL/!d;s/^URL: //'` - cd "$here" - projname=`$SVN propget project "$change_log_dir"` # Try to be VCS-compatible and find a project name in a *.rb. if [ x"$projname" = x ] && [ -d "$change_log_dir/vcs" ]; then @@ -401,9 +494,10 @@ in " "$change_log_dir"/vcs/*.rb d;q }'` - # Files to put in the ChangeLog entry. change_log_files=`echo "$my_svn_st" | sed ' + t dummy_sed_1 + : dummy_sed_1 s/^M......\(.*\)$/ * \1: ./; t s/^A......\(.*\)$/ * \1: New./; t s/^D......\(.*\)$/ * \1: Remove./; t @@ -452,10 +546,10 @@ $change_log_files --This line, and those below, will be ignored-- $commit_instructions - --Preview of the message that will be sent-- Repository: $repos_root +Next revision: $REV Your comments (if any) will appear here. ChangeLog: @@ -581,7 +675,7 @@ $svn_diff" | sed 's/^\.$/ ./' >"$mail_file" if (grep '^sign: false' ~/.vcs) >/dev/null 2>/dev/null; then :; else ($GPG -h) >/dev/null 2>/dev/null gpg_rv=$? - if [ -f ~/.gnupg ] || [ -f ~/.gpg ] || [ -f ~/.pgp ] && [ $gpg_rv -gt 42 ] + if [ -e ~/.gnupg ] || [ -e ~/.gpg ] || [ -e ~/.pgp ] && [ $gpg_rv -lt 42 ] then yesno "Sign the mail using $GPG ?" && \ $GPG --clearsign "$mail_file" -- 2.11.4.GIT