2 # Simple wrapper around svn featuring auto-ChangeLog entries and emailing.
4 # Copyright (C) 2006 Benoit Sigoure.
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 # Quick install: alias svn=path/to/svn-wrapper.sh -- that's all.
27 # This script is a wrapper around the svn command-line client for UNIX. It has
28 # been designed mainly to automagically generate GNU-style ChangeLog entries
29 # when committing and mail them along with a diff and an optional comment from
30 # the author to a list of persons or a mailing list. It has been made so that
31 # it's as much portable as possible and covers as many use-case as possible.
33 # HOWEVER, there will be bugs, there will be cases in which the script doesn't
34 # wrap properly the svn-cli, etc. In this case, you can try to mail me at
35 # <tsuna at lrde dot epita dot fr>. Include the revision of the svn-wrapper
36 # you're using, and full description of what's wrong etc. so I can reproduce
39 # If you feel like, you can try to fix/enhance the script yourself. It only
40 # requires some basic Shell-scripting skills. Knowing sed might help :)
46 # If you're simply looking for the usage, run svn-wrapper.sh help (or
47 # svn help if you aliased `svn' on svn-wrapper.sh) as usual.
49 # This script is (hopefully) portable, widely commented and self-contained. Do
50 # not hesitate to hack it. It might look rather long (because it does a lot of
51 # things :P) but you should be able to easily locate which part of the code
54 # The script begins by defining several functions. Then it really starts where
55 # the comment "# `main' starts here. #" is placed.
56 # Some svn commands are hooked (eg, svn st displays colors). Hooks and
57 # extra commands are defined in functions named svn_<command-name>.
63 # * Handle things such as svn ci --force foobar.
64 # * Automatic proxy configuration depending on the IP in ifconfig?
65 # * Customizable behavior/colors via some ~/.<config>rc file (?)
66 # * Improve Auto-Emailing (if possible in sh :|)
70 # Default values (the user can export them to override them).
79 # Override the locale.
83 # No args, invoke svn...
84 test $# -lt 1 && exec $SVN
88 # The `main' really starts after the functions definitions.
96 red
='\e[0;31m'; lred
='\e[1;31m'
97 green
='\e[0;32m'; lgreen
='\e[1;32m'
98 yellow
='\e[0;33m'; lyellow
='\e[1;33m'
99 blue
='\e[0;34m'; lblue
='\e[1;34m'
100 purple
='\e[0;35m'; lpurple
='\e[1;35m'
101 cyan
='\e[0;36m'; lcyan
='\e[1;36m'
102 grey
='\e[0;37m'; lgrey
='\e[1;37m'
103 white
='\e[0;38m'; lwhite
='\e[1;38m'
111 yellow
=''; lyellow
=''
113 purple
=''; lpurple
=''
123 echo "svn-wrapper: ${lred}abort${std}: $@" |
sed '1!s/^/ /' >&2
130 echo "svn-wrapper: ${lred}warning${std}: $@" |
sed '1!s/^/ /' >&2
136 echo "svn-wrapper: ${lyellow}notice${std}: $@" |
sed '1!s/^/ /' >&2
143 read answer ||
return 1
148 return 42 # should never happen...
154 warn
"cannot find the environment variable $1
155 You might consider using \`export $1 <FIXME>\`"
158 # get_unique_file_name file-name
159 get_unique_file_name
()
162 echo "$1" && return 0
165 while test -f "$gufn.$i"; do
171 # ensure_not_empty description value
174 ene_val
=`echo "$2" | tr -d ' \t\n'`
175 test x
"$ene_val" = x
&& abort
"$1: empty value"
181 my_url
='http://www.lrde.epita.fr/~sigoure/svn-wrapper'
182 # You can use https if you feel paranoiac.
184 echo ">>> Fetching svn-wrapper.sh from $my_url/svn-wrapper.sh"
186 # --------------------- #
187 # Fetch the new version #
188 # --------------------- #
190 tmp_me
=`get_unique_file_name "$TMPDIR/svn-wrapper.sh"`
191 if (wget
--help) >/dev
/null
2>/dev
/null
; then
192 wget
--no-check-certificate "$my_url/svn-wrapper.sh" -O "$tmp_me"
195 curl
--help >/dev
/null
2>/dev
/null
197 if [ $?
-gt 42 ]; then
198 abort
'Cannot find wget or curl.
199 How can I download any update without them?'
201 curl
--insecure "$my_url/svn-wrapper.sh" >"$tmp_me"
205 || abort
"Can't find the copy of myself I downloaded in $tmp_me"
207 # ---------------------------------------- #
208 # Compare versions and update if necessary #
209 # ---------------------------------------- #
211 tmp_ver
=`sed '/^# $Id[:].*$/!d;
214 s/[^0-9]*\([0-9][0-9]*\).*/\1/' "$tmp_me"`
215 my_ver
=`sed '/^# $Id[:].*$/!d;
218 s/[^0-9]*\([0-9][0-9]*\).*/\1/' "$0"`
219 if [ $my_ver -lt $tmp_ver ]; then # There IS an update...
220 echo "An update is available, r$tmp_ver (your version is r$my_ver)"
223 if yesno
"Do you want to see the ChangeLog between r$my_ver and r$tmp_ver?"
225 my_chlog
=`get_unique_file_name "$TMPDIR/ChangeLog"`
227 wget
) wget
--no-check-certificate "$my_url/ChangeLog" -O "$my_chlog"
229 curl
) curl
--insecure "$my_url/ChangeLog" >"$my_chlog"
231 *) abort
'Should never be here.'
234 sed "/^r$my_ver/q" "$my_chlog" |
$PAGER
238 # Wanna see the diff?
239 if yesno
"Do you want to see the diff between r$my_ver and r$tmp_ver?"
241 (diff -uw "$0" "$tmp_me" | diffstat
;
243 diff -uw "$0" "$tmp_me") |
$PAGER
247 if yesno
"Overwrite $0 (r$my_ver) with $tmp_me (r$tmp_ver)?"; then
249 mv "$tmp_me" "$0" && exit 0
253 elif [ $my_ver -gt $tmp_ver ]; then
254 echo "Wow, you're more up to date than the master copy :)"
255 echo "Your version is r$my_ver and the master copy is r$tmp_ver."
257 echo "You're already up to date [r$my_ver] :)"
262 # ------------------------------- #
263 # Hooks for standard SVN commands #
264 # ------------------------------- #
266 # svn_commit [args...]
273 here
=`pwd`; found
=0; change_log_files
=''
274 while [ $found -eq 0 ]; do
275 if [ -f .
/ChangeLog
]; then
280 change_log_dir
=`pwd -P`
281 # Stop searching when in / ... hmz :P
282 test x
"$change_log_dir" = x
/ && {
283 if yesno
'svn-wrapper: Error: Cannot find a ChangeLog file!
284 You might want to create an empty one (eg: `touch ChangeLog` where appropriate)
285 Do you want to proceed without using a ChangeLog?'; then
287 $SVN commit
"$@" && $SVN update
294 notice
"using $change_log_dir/ChangeLog"
296 # Warn for files that are not added in the repos.
297 conflicts
=`$SVN status | sed '/^\?/!d'`
298 if test x
"$conflicts" != x
; then
299 warn
"make sure you don't want to \`svn add'
300 any of the following files before committing:"
301 echo "$conflicts" |
sed "$sed_svn_st_color"
302 echo -n "Type [ENTER] to continue :)" && read chiche_is_gay
305 # Detect unresolved conflicts / missing files.
306 conflicts
=`$SVN status | sed '/^[C!]/!d'`
307 test x
"$conflicts" != x
&& abort
"there are unresolved conflicts (\`C')
308 and/or missing files (\`!'):
311 $SVN update || abort
'svn update failed.'
316 REV
=`$SVN info | sed '/^Revision: /!d;s///'`
317 test x
"$REV" = x
&& REV
=`$SVN info | sed '/^Last Changed Rev: /!d;s///'`
318 test x
"$REV" = x
&& warn
'Cannot detect the current revision.'
321 tmp_log
="$change_log_dir/,svn-log"
322 if [ -f "$tmp_log" ] && yesno
"It looks like the last commit did not\
323 terminate successfully.
324 Would you like to resume it?"; then
326 internal_tags
=`sed '/^--- Internal stuff, DO NOT change please ---$/,$!d' \
328 saved_args
=`echo "$internal_tags" | sed '/^args: */!d;s///'`
329 if [ x
"$saved_args" != x
]; then
330 if [ x
"$@" != x
] && [ x
"$saved_args" != x
"$@" ]; then
331 warn
"overriding arguments:
332 you invoked $0 with the following arguments: $@
333 they have been replaced by these: $saved_args"
334 set dummy
"$saved_args"
337 notice
"setting the following arguments: $saved_args"
338 set dummy
"$saved_args"
342 # Ignore white spaces. Can't svn diff -x -w: svn 1.4 only.
343 svn_diff
=`$SVN diff --diff-cmd diff -x -uw "$@"`
344 test x
"$svn_diff" = x
&& svn_diff
=`$SVN diff "$@"`
345 svn_diff_stat
=`echo "$svn_diff" | diffstat`
347 else # Build the template message.
349 # ------------------------------------ #
350 # Gather info for the template message #
351 # ------------------------------------ #
353 repos_root
=`$SVN info | sed '/^Repository Root/!d;s/^Repository Root: //'`
354 # It looks like svn <1.3 didn't display a "Repository Root" entry.
355 test x
"$repos_root" = x
&& \
356 repos_root
=`$SVN info | sed '/^URL/!d;s/^URL: //'`
359 projname
=`$SVN propget project "$change_log_dir"`
360 # Try to be VCS-compatible and find a project name in a *.rb.
361 if [ x
"$projname" = x
] && [ -d "$change_log_dir/vcs" ]; then
362 projname
=`sed '/common_commit/!d;s/.*"\(.*\)<%= rev.*/\1/' \
363 "$change_log_dir"/vcs/*.rb`
364 test x
"$projname" != x \
365 && notice
"VCS-compat: found project name: $projname
366 in " "$change_log_dir"/vcs
/*.rb
368 test x
"$projname" != x
&& projname
=`echo "$projname" | sed '/[^ ]$/s/$/ /'`
370 mailto
=`$SVN propget mailto "$change_log_dir"`
371 if [ x
"$mailto" = x
]; then
372 warn
"no svn property mailto found in $change_log_dir
373 You might want to set default email adresses using:
374 svn propset mailto 'somebody@mail.com, foobar@example.com'\
376 # Try to be VCS-compatible and find a list of mails in a *.rb.
377 if [ -d "$change_log_dir/vcs" ]; then
378 mailto
=`grep '.@.*\..*' "$change_log_dir"/vcs/*.rb \
380 | sed 's/^.*[["]\([^["]*@[^]"]*\)[]"].*$/\1/' | xargs`
381 test x
"$mailto" != x
&& notice
"VCS-compat: found mailto: $mailto
382 in " "$change_log_dir"/vcs
/*.rb
384 fi # end guess mailto
386 # Ensure that emails are comma-separated.
387 mailto
=`echo "$mailto" | sed 's/[ ;]/,/g' | tr -s ',' | sed 's/,/, /g'`
388 test x
"$FULLNAME" = x
&& FULLNAME
='Type Your Name Here' \
390 test x
"$EMAIL" = x
&& EMAIL
='your.mail.here@FIXME.com' && warn_env EMAIL
392 # --ignore-externals appeared after svn 1.1.1
393 my_svn_st
=`$SVN status --ignore-externals "$@" \
394 || $SVN status "$@" | sed '/^Performing status on external/ {
399 # Files to put in the ChangeLog entry.
400 change_log_files
=`echo "$my_svn_st" | sed '
401 s/^M......\(.*\)$/ * \1: ./; t
402 s/^A......\(.*\)$/ * \1: New./; t
403 s/^D......\(.*\)$/ * \1: Remove./; t
406 if [ x
"$change_log_files" = x
]; then
407 yesno
'Nothing to commit, continue anyway?' ||
return 1
410 svn_diff
=`$SVN diff --diff-cmd diff -x -uw "$@"`
411 svn_diff_stat
=`echo "$svn_diff" | diffstat`
413 # Get any older svn-log out of the way.
414 test -f "$tmp_log" && mv "$tmp_log" `get_unique_file_name "$tmp_log"`
415 # If we can't get an older svn-log out of the way, find a new name...
416 test -f "$tmp_log" && tmp_log
=`get_unique_file_name "$tmp_log"`
417 commit_instructions
='
419 - Fill the ChangeLog entry.
420 - If you feel like, write a comment in the "Comment:" section.
421 This comment will only appear in the email, not in the ChangeLog.
422 By default only the location of the repository is in the comment.
423 - Some tags will be replaced. Tags are of the form: <TAG>. Unknown
424 tags will be left unchanged.
425 - Your ChangeLog entry will be used as commit message for svn.'
426 # VCS-compat: handle user option 'new_user'
427 grep '^new_user: false' ~
/.vcs
>/dev
/null
2>/dev
/null \
428 && commit_instructions
=''
430 --You must fill this file correctly to continue-- -*- vcs -*-
432 Subject: ${projname}r<REV>: <TITLE>
433 From: $FULLNAME <$EMAIL>
437 Repository: $repos_root
441 <YYYY>-<MM>-<DD> $FULLNAME <$EMAIL>
447 --This line, and those below, will be ignored--
450 --Preview of the message that will be sent--
452 Repository: $repos_root
453 Your comments (if any) will appear here.
456 $YYYY-$MM-$DD $FULLNAME <$EMAIL>
458 Your ChangeLog entry will appear here.
462 $svn_diff" >"$tmp_log"
465 --- Internal stuff, DO NOT change please ---
466 args: $@" >>"$tmp_log"
468 fi # end: if svn-log; then resume? else create template
471 # ------------------ #
472 # Re-"parse" the log #
473 # ------------------ #
475 # hmz this section is a bit messy...
476 sed_escape
='s/@/\\@/' # helper string... !@#$%* escaping \\\\\\...
477 sed_eval_tags
="s/<MM>/$MM/g; s/<DD>/$DD/g; s/<YYYY>/$YYYY/g; s/<REV>/$REV/g"
478 full_log
=`sed '/^--This line, and those below, will be ignored--$/,$d;
479 /^--You must fill this/d' "$tmp_log"`
480 chlog_entry
=`echo "$full_log" | sed '/^ChangeLog:$/,$!d; //d'`
481 ensure_not_empty
'ChangeLog entry' "$chlog_entry"
482 full_log
=`echo "$full_log" | sed '/^ChangeLog:$/,$d'`
483 mail_comment
=`echo "$full_log" | sed '/^Comment:$/,$!d; //d'`
484 full_log
=`echo "$full_log" | sed '/^Comment:$/,$d'`
485 mail_title
=`echo "$full_log" | sed '/^Title: */!d;s///'`
486 ensure_not_empty
'commit title' "$mail_title"
487 mail_title
=`echo "$mail_title" | sed "$sed_eval_tags; $sed_escape"`
488 sed_eval_tags
="$sed_eval_tags; s@<TITLE>@$mail_title@g"
489 mail_comment
=`echo "$mail_comment" | sed "$sed_eval_tags"`
490 chlog_entry
=`echo "$chlog_entry" | sed "$sed_eval_tags; 1{
493 mail_subject
=`echo "$full_log" | sed '/^Subject: */!d;s///'`
494 ensure_not_empty
'mail subject' "$mail_subject"
495 mail_subject
=`echo "$mail_subject" | sed "$sed_eval_tags"`
496 mail_to
=`echo "$full_log" | sed '/^To:/!d'`
498 if test x
"$mail_to" = x
; then
501 mail_to
=`echo "$mail_to" | sed 's/^To: *//'`
502 ensure_not_empty
'"To:" field of the mail' "$mail_to"
504 mail_from
=`echo "$full_log" | sed '/^From: */!d;s///'`
505 ensure_not_empty
'"From:" field of the mail' "$mail_from"
507 # Check whether the user passed -m | --message
509 while [ $i -lt $# ]; do
511 # This is not really a reliable way of knowing whether -m | --message was
512 # passed but hum... Let's assume it'll do :s
513 test x
"$arg" = 'x-m' && has_message
=1
514 test x
"$arg" = 'x--message' && has_message
=1
516 set dummy
"$@" "$arg"
520 if [ $has_message -eq 0 ]; then
521 my_message
=`echo "$chlog_entry" | grep -v "^$YYYY-$MM-$DD" | sed '1,2 {
524 set dummy
--message "$my_message" "$@"
527 notice
'you are overriding the commit message.'
531 yesno
'Are you sure you want to commit?' ||
return 1
533 # Add the ChangeLog entry
534 old_chlog
=`get_unique_file_name "$change_log_dir/ChangeLog.old"`
535 mv "$change_log_dir/ChangeLog" "$old_chlog" || \
536 abort
'Could not backup ChangeLog'
537 trap "echo SIGINT; mv \"$old_chlog\" \"$change_log_dir/ChangeLog\"" SIGINT
538 echo "$chlog_entry" >"$change_log_dir/ChangeLog"
539 echo >>"$change_log_dir/ChangeLog"
540 cat "$old_chlog" >>"$change_log_dir/ChangeLog"
542 # --Commit-- finally! :D
543 $SVN commit
"$@" ||
{
544 mv "$old_chlog" "$change_log_dir/ChangeLog"
545 abort
"Commit failed, $SVN returned $?"
548 # In the end, perform an svn up to update externals
549 $SVN update
"$change_log_dir"
553 if test x
$send_a_mail = xyes
; then
554 mail_file
=`get_unique_file_name "$change_log_dir/+mail"`
558 Subject: $mail_subject
567 $svn_diff" |
sed 's/^\.$/ ./' >"$mail_file"
568 # We change lines with only a `.' because they could mean "end-of-mail"
570 trap 'echo SIGINT; exec < /dev/null' SIGINT
571 test -f ~
/.signature
&& echo '-- ' >>"$mail_file" && \
572 cat ~
/.signature
>>"$mail_file"
573 # VCS-compat: handle user option 'sign'.
574 if (grep '^sign: false' ~
/.vcs
) >/dev
/null
2>/dev
/null
; then :; else
575 ($GPG -h) >/dev
/null
2>/dev
/null
577 if [ -f ~
/.gnupg
] ||
[ -f ~
/.gpg
] ||
[ -f ~
/.pgp
] && [ $gpg_rv -gt 42 ]
579 yesno
"Sign the mail using $GPG ?" && \
580 $GPG --clearsign "$mail_file"
581 test -f "$mail_file.asc" && mv "$mail_file.asc" "$mail_file"
584 # FIXME: This looks a bit fragile. What if $mail_to = -s foo ? Will it
585 # override the previous -s option?
586 cat "$mail_file" |
mail -s "$mail_subject" "$mail_to"
587 fi # end do we have to send a mail?
590 save_mail_file
=`echo "$mail_file" | sed 's/+//'`
591 if [ -d "$change_log_dir/vcs" ] \
592 ||
[ -d "$change_log_dir/+committed" ]
594 mkdir
-p "$change_log_dir/+committed/$REV" \
595 && mv "$mail_file" "$change_log_dir/+committed/$REV/mail"
597 return $svn_commit_rv
603 echo "Using svn-wrapper v$version (C) SIGOURE Benoit [GPL]"
604 sed '/^# $Id[:].*$/!d;s/.*$Id[:] *//;s/ *$ *//;s/ \([0-9][0-9]*\)/ (r\1)/' "$0"
607 # has_prop prop-name [path]
608 # return value: 0 -> path has the property prop-name set.
609 # 1 -> path has no property prop-name.
613 hp_plist
=`$SVN proplist "$2"`
614 test $?
-ne 0 && return 2
615 hp_res
=`echo "$hp_plist" | sed "/^ *$1\$/!d"`
616 test x
"$hp_res" = x
&& return 1
620 # svn_propadd prop-name prop-val [path]
624 && abort
'Not enough arguments provided; try `svn help propadd` for more info'
626 && abort
'Too many arguments provided; try `svn help propadd` for more info'
629 test x
"$path" = x
&& path
='.' && set dummy
"$@" '.' && shift
630 has_prop
"$1" "$3" ||
{
631 test $?
-eq 2 && return 1 # svn error
633 yesno
"'$path' has no property named '$1', do you want to add it?" \
638 current_prop_val
=`$SVN propget "$1" "$3"`
639 test $?
-ne 0 && abort
"Failed to get the current value of property '$1'."
641 $SVN propset
"$1" "$current_prop_val
642 $2" "$3" >/dev
/null || abort
"Failed to add '$3' in the property '$1'."
644 current_prop_val
=`$SVN propget "$1" "$3" || echo "$current_prop_val
646 echo "property '$1' updated on '$path', new value:
650 # svn_propsed prop-name sed-script [path]
654 && abort
'Not enough arguments provided; try `svn help propsed` for more info'
656 && abort
'Too many arguments provided; try `svn help propsed` for more info'
659 test x
"$path" = x
&& path
='.'
660 has_prop
"$1" "$3" ||
{
661 test $?
-eq 2 && return 1 # svn error
663 abort
"'$path' has no property named '$1'."
666 prop_val
=`$SVN propget "$1" "$3"`
667 test $?
-ne 0 && abort
"Failed to get the current value of property '$1'."
669 prop_val
=`echo "$prop_val" | sed "$2"`
670 test $?
-ne 0 && abort
"Failed to run the sed script '$2'."
672 $SVN propset
"$1" "$prop_val" "$3" >/dev
/null \
673 || abort
"Failed to update the property '$1' with value '$prop_val'."
675 new_prop_val
=`$SVN propget "$1" "$3" || echo "$prop_val"`
676 echo "property '$1' updated on '$path', new value:
683 if [ $# -eq 0 ]; then # Simply display ignore-list.
684 $SVN propget
'svn:ignore'
685 elif [ $# -eq 1 ]; then
686 if [ -d "$1" ]; then # Display ignore-list for $1
687 $SVN propget
'svn:ignore' "$1"
688 elif [ x
`dirname "$1"` != x.
]; then
689 # Add `basename $1` in the ignore-list of `dirname $1`
690 i_basename
=`basename "$1"`
691 i_dirname
=`dirname "$1"`
692 svn_propadd
'svn:ignore' "$i_basename" "$i_dirname"
693 else # Add $1 in ignore-list of `.'.
694 svn_propadd
'svn:ignore' "$1"
696 else # Add arguments in svn:ignore.
698 while [ $i -lt $# ]; do
701 if [ $i -eq $# ]; then
704 set dummy
"$@" "$arg"
709 i_files
=`echo "$*" | tr -s ' ' '\n'`
710 if [ -d "$last_arg" ]; then # Add in ignore-list of $last_arg
711 svn_propadd
'svn:ignore' "$i_files" "$last_arg"
712 else # Add in ignore-list of `.'
713 svn_propadd
'svn:ignore' "$i_files
722 if [ $# -eq 0 ]; then
727 Additionnal commands provided by svn-wrapper:
740 echo 'diffstat (ds): Display the histogram from svn diff-output.'
741 $SVN help diff |
sed '1d;
742 s/differences*/histogram/;
743 2,35 s/diff/diffstat/g'
746 echo 'ignore: Add some files in the svn:ignore property.
747 usage: 1. ignore [PATH]
748 2. ignore FILE [FILES...] [PATH]
750 1. Display the value of svn:ignore property on [PATH].
751 2. Add some files in the svn:ignore property of [PATH].
753 If you want to add directories in the ignore-list, be careful:
755 will add "foo/" in the property svn:ignore within the directory bar!
757 svn ignore foo/ bar/ .
758 (It'\''s somewhat like with mv)
764 echo 'propadd (padd, pa): Add something in the value of a property.
765 usage: propadd PROPNAME PROPVAL PATH
767 PROPVAL will be appended at the end of the property PROPNAME.
773 echo 'propsed (psed): Edit a property with sed.
774 usage: propsed PROPNAME SED-ARGS PATH
776 eg: svn propsed svn:externals "s/http/https/" .
782 echo 'revision (rev): Display the revision number of a local or remote item.'
783 $SVN help info |
sed '1d;
784 s/information/revision/g;
785 s/revision about/the revision of/g;
786 2,35 s/info/revision/g;
790 echo 'touch: Touch a file and svn add it.
791 usage: touch FILE [FILES]...
796 selfupdate | selfup | self-update | self-up
)
797 echo 'selfupdate (selfup): Attempt to update svn-wrapper.sh
804 echo 'version: Display the version info of svn and svn-wrapper.
815 # svn_status [args...]
818 $SVN status
"$@" |
sed "$sed_svn_st_color"
822 # ------------------- #
823 # `main' starts here. #
824 # ------------------- #
827 if (echo | diffstat
) >/dev
/null
2>/dev
/null
; then :; else
828 warn
'diffstat is not installed on your system or not in your PATH.'
829 test -f /etc
/debian_version \
830 && notice
'you might want to `apt-get install diffstat`.'
832 if (echo |
mail) >/dev
/null
2>/dev
/null
; then :; else
833 if [ $?
-gt 100 ]; then
834 warn
'mail is not installed on your system or not in your PATH.'
835 test -f /etc
/debian_version \
836 && notice
'you might want to:
837 # apt-get install mailx
838 # dpkg-reconfigure exim'
842 # Define colors if stdout is a tty.
845 else # stdout isn't a tty => don't print colors.
849 # Considere this as a sed function :P.
855 s/^\\(.\\)C/\\1${lred}C${std}/
858 s/^\\?/${lred}?${std}/; t
859 s/^M/${lgreen}M${std}/; t
860 s/^A/${lgreen}A${std}/; t
861 s/^X/${lblue}X${std}/; t
862 s/^+/${lyellow}+${std}/; t
863 s/^D/${lyellow}D${std}/; t
864 s/^,/${lred},${std}/; t
865 s/^C/${lred}C${std}/; t
866 s/^I/${purple}I${std}/; t
867 s/^R/${lblue}R${std}/; t
868 s/^!/${lred}!${std}/; t
869 s/^~/${lwhite}~${std}/; t"
872 test "x$1" = x--debug
&& shift && set -x
875 # ------------------------------- #
876 # Hooks for standard SVN commands #
877 # ------------------------------- #
890 # -------------------- #
891 # Custom SVN commands #
892 # -------------------- #
895 $SVN diff "$@" | diffstat
911 $SVN info
"$@" |
sed '/^Revision/!d;s/^Revision: //'
915 touch "$@" && svn add
"$@"
917 selfupdate | selfup | self-update | self-up
)
921 version |
-version |
--version)
923 set dummy
'--version' "$@"