#!/bin/sh
#                               -*- Mode: Sh -*-
# hook ---
# Author           : Manoj Srivastava ( srivasta@golden-gryphon.com )
# Created On       : Sat May 3 00:53:06 2003
# Created On Node  : anzu.internal.golden-gryphon.com
# Last Modified By : Manoj Srivastava
# Last Modified On : Mon Aug 20 13:51:18 2007
# Last Machine Used: anzu.internal.golden-gryphon.com
# Update Count     : 56
# Status           : Working revision.
# HISTORY          :
# Description      : This is the hook script called by arch for every
#                    action taken, and is used to customize the behaviour
#                    of arch.
#
# arch-tag: 58104430-9dd2-4300-bbcd-af0f5f4545ad
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#

##
## Before the hook script is called, arch arranges to have certain
## envirnment variables set. Not all variables are set for all
## commands; the list below gives the variables and the commands for
## which they are set. The actual command is present in the first
## argument.
##

# ARCH_ACTION: alway
#   gives the current action being taken
ARCH_ACTION="$1"

# ARCH_ARCHIVE: always
#   represents the registered name of the archive on which the action
#   is being performed
#
# ARCH_LOCATION: make-archive
#   gives the location of the archive being prepared by tla
#
# ARCH_REVISION: import, tag, commit, find-pristine, make-pristine
#   gives the exact revision being (import|tagg|commit)ed.
#
# ARCH_CATEGORY: make-category
#   gives the category being prepared (format: category)
#
# ARCH_BRANCH: make-branch
#   gives the branch being prepared (format: category--branch)
#
# ARCH_VERSION: make-version
#   gives the version being prepared (format: category--branch--version)
#
# ARCH_TREE_ROOT: commit, import
#   gives the location of the working tree from which tla is performing
#   the action
#
# ARCH_TAGGED_ARCHIVE: tag
#   gives the archive of the revision from which tla will create the tag
#
# ARCH_TAGGED_REVISION
#   gives the revision from which tla will create the tagged version
#
# ARCH_LOG: commit, tag, import
#   Contains the name of a file containing the full text for the newly
#   created log file (the file pointed to by ARCH_LOG may be
#   temporary). This is in baz 1.5 and greater only.
#

# Allow selection of tla or baz
CMD=tla
# Default address to mail notifications to
MAILTO=srivasta
# How often to cache versions
CACHE_EVERY=20;

# Logging convenience function
hookLog() {
    echo "hook:  $@"
}

# Create a debug output file safely.
if [ -x /bin/tempfile ]; then
    HOOK_OUT=$(tempfile -p hook -m 0600 );
else
    set -e
    mkdir /tmp/hook$$
    HOOK_OUT=/tmp/hook$$/out
    set +e
fi

# Debug stuff.
if [ "$ARCH_HOOK_DEBUG" == "1" ]; then
    echo "$@"  >> $HOOK_OUT
    env | sort >> $HOOK_OUT
    echo ""    >> $HOOK_OUT
fi

##
## Allow for an per-project hook script. On collaborative projects,
## each contributor must have his own copy of the hook script, and
## keep it up to date with some master copy; there is no standard
## mechanism for arranging such synchronisation. It would clearly be
## convenient if the hook scripts for a project could be kept in the
## project tree itself; I don't generally use it.'
##
extra_hook="$ARCH_TREE_ROOT/{arch}/=hook"
if [ -x "$extra_hook" ] ;  then
  : echo "$extrahook" $@
fi

##
## This is a kludge.  This is a list of arch categories for which we
## send mail to ${package}_cvs@packages.qa.debian.org.  I wish there
## was something more elegant.
##
PACKAGES="angband angband-doc c2man calc checkpolicy cvs-buildpackage debian-policy dist flex flex-old fvwm gnus kernel-package libcgi-perl libgraphics-colordeficiency-perl libgraphics-colornames-perl libgraphics-colorobject-perl liblog-log4perl-perl libmodule-load-perl libselinux libsemanage libsepol mailagent make make-dfsg make-doc-non-dfsg polgen-dfsg polgen-doc-non-dfsg policycoreutils psgml refpolicy selinux-doc sepolgen setools slat tla-tools tome ucf vm wm-icons"

##
## This helpre function is a simple wrapper around sendmail, and is
## used through out this hook to send mail. This is a drop in
## replacement of mailx.
##  Takes three arguments:
##    The first argument is a literal -s
##    The second argument is a subject
##    The Third argument is the recipient mail address
## The body is read in from STDIN.
##
sendmail_wrapper()
{
    if [ $# -ne 3 ] ; then
        echo 1>&2 "sendmail usage error: need 3 arguments"
	exit 1
    fi
    if [ "$1" != "-s" ] ; then
        echo 1>&2 "sendmail usage error: first argument must be -s"
        exit 1
    fi
    (
        cat <<EOF
To: $3
BCC: srivasta@debian.org
Subject: $2
X-PTS-Approved: Yes


EOF
        cat
    )  | /usr/sbin/sendmail -oi -t
}

##
## This helper function essentially is a complex awk function that
## reads and arch Log entry, and formats it for a mail message.  This
## function takes no arguments, and reads arch log entries from
## STDIN. It is also used to sanitize the input when we look for
## Closes: entr5ies in the commit log while looking forbugs that might
## have been fixed for this commit.
##
cl_entry()
{
    awk -v archive="$archive" \
        -v version="$version" \
        -v category="$category" \
        -v branch="$branch" \
        -v patch="$patch" \
        -v no_files="$no_files" \
        'BEGIN { getline;
             while (!match ($0, "^$"))
               {
                 field = tolower ($1);
                 sub (":.*", "", field);
                 headers[field] = $0;
                 sub ("^[^:]*:[ \t]*", "", headers[field]);
                 getline;
                 while (match ($0, "^[ \t]"))
                   {
                     headers[field] = headers[field] $0;
                     getline;
                   }
               }
           }

     { if (body == "") body = "    " $0; else body = body "\n    " $0; }

     END {
           date = headers["standard-date"];
           author = headers["creator"];
           summary = headers["summary"];
           revision = headers["revision"]

           if (date == "")
             {
	       # this is almost vestigial: a backwards compatibility
	       # hack just for the author of arch, some of whose log
	       # messages pre-date the "standard-date" header field.
	       #
               split (headers["date"], ugly_date, "[ \t]+");
               date = ugly_date[6] "-" ugly_date[2] "-" ugly_date[3];
             }
	   sub("[[:space:]].*GMT.*", " GMT", date);
           print date "\t" author "\t" patch;
           print "";
           print "    Summary:";
           print "      " summary;
           print "    Revision:";
           print "      " revision;
           print "";
           print body;
           print "";
           if (no_files == "")
             {
               file_list(0, "new-files", "{arch}/" category "/" branch "/" version "/" archive "/patch-log/" patch);
               file_list(0, "removed-files");
               file_list(0, "modified-files");
	       file_pair_list("renamed-files");
               file_list(0, "new-directories");
               file_list(0, "removed-directories");
               file_list(0, "modified-directories");
	       file_pair_list("renamed-directories");
               file_list(0, "new-patches", archive "/" version "--" patch);
               print ""
             }
     }

     function file_list (base_only, field_name, exclude)
     {
         for (x in items)
         delete items[x];

         n_items = split (headers[field_name], items, "[ \t]+");

         if ((n_items == 0) || ((exclude != "") && (n_items == 1)))
             return;

             sub("-", " ", field_name);
             print "    " field_name ":"
             printf("    ");
             width = 0;
             items_on_line = 0;

             for (x = 1; x <= n_items; ++x)
             {
                 if (exclude == items[x])
                     continue;
                     if (base_only)
                         sub (".*/", "", items[x]);
                         if ((items_on_line == 0) || ((width + length (items[x]) + 1) < 64))
                             {
                                 width += length (items[x]) + 1;
                                 ++items_on_line;
                                 printf(" %s", items[x]);
                             }
                         else
                             {
                                 printf("\n");
                                 printf("    ");
	                         printf(" %s", items[x]);
                                 width = length(items[x]) + 1;
                                 items_on_line = 1;
                             }
             }
             printf "\n"
             printf "\n"
     }
     function file_pair_list (field_name)
     {
         for (x in items)
         delete items[x];

         n_items = split (headers[field_name], items, "[ \t]+");

       if (n_items == 0)
         return;

       sub("-", " ", field_name);
       print "    " field_name ":"

       for (x = 1; x <= n_items; ++x)
         {
	   printf("     %s\n", items[x]);
	   printf("       ==> %s\n", items[x + 1]);
	   x = x + 1;
         }
       printf "\n"
       printf "\n"
     }'
}

##
## This is a helper function which uses the same hueristic the Debian
## BTS uses when looking for bugs to close in a package's
## debian/changelog entry.  This function uses the cl_entry function
## to sanitize the arch log; parses it for bugs that have been fixed,
## and sends the clensed log entry to the bug report, as well as
## tagging the bug pending.
##
## This is useful when a new pload is worked on over an extended
## period of time, as it helps automate communication of the bug
## status and work done, even though an upload is not currently
## forthcoming.
##
update_bug()
{
    changes=$($CMD cat-archive-log "${ARCH_ARCHIVE}/${ARCH_REVISION}" | cl_entry )
    echo "$changes" | perl -e '
my %Seen;
{
  local $/; # enable localized slurp mode
  my $string=<>;
  while ( $string =~ m/closes:\s*(?:bug)?\#\s*\d+(?:,\s*(?:bug)?\#\s*\d+)*/gsmi ) {
    my $match="$&";
    while ($match =~ /(\d+)/g) {
      $Seen{$1}++;
    }
  }
}
for (sort keys %Seen) { print "$_\n"; }
' | while read bug; do
        echo |         \
            sendmail_wrapper -s "Fix for Bug#$bug commited to version control" \
            $bug@bugs.debian.org,control@bugs.debian.org<<EOF
tags $bug +pending
thanks
Hi,

     The following change has been committed for this bug, and so the
  fix will be in the next upload.
===================================================================
$changes


EOF

    done
}

##
## cache a full source tree in the repository.  This can speed up
## subsequent calls to get for that and subsequent revisions.
##
update_library()
{
    local buf=""

    buf="$($CMD library-add --sparse "${ARCH_ARCHIVE}/${ARCH_REVISION}" 2>&1)"
    if [ $? -ne 0 ] ; then
        ##
        ## If something goes wrong while caching, send notifications.
        ##
        hookLog "Sending failure notice of caching ${ARCH_REVISION} to $MAILTO"

        echo "$buf" |         \
            sendmail_wrapper -s "$CMD library-add ${ARCH_ARCHIVE}/${ARCH_REVISION} failed" \
            $MAILTO
        return 1
    fi
    return 0
}

##
## This helper functions helps to update mirror archives whenever a
## change is made to the local archive.  If the mirroring failsm it
## sends a failure notice.
##
update_mirror()
{
    mirror="${1}"
    limit=$($CMD parse-package-name --package-version $ARCH_REVISION)
    local buf=""

    ## must delete ARCH_ARCHIVE variable since this $CMD instance will
    ## not override it, thus when it calls this hook again we won't be
    ## able to tell that we are operating on the mirror, resulting in
    ## duplicate mails
    buf="$(env -u ARCH_ARCHIVE $CMD archive-mirror "${ARCH_ARCHIVE}" "$mirror" "$limit" || true)"
    if [ $? -ne 0 ] ; then
        ##
        ## If something goes wrong while mirroring, send
        ## notifications.
        ##
        hookLog "Sending failure notice of mirroring of ${ARCH_REVISION} to $MAILTO"
	echo "$buf" |    \
            sendmail_wrapper -s "$CMD archive-mirror ${ARCH_ARCHIVE} $limit failed" \
            $MAILTO
	return 1
    fi

    return 0
}

##
## This helper function generates the body of the optional
## notification sent when a new category is created.  This may be
## used to send announcements of new revisions to subscribers of the
## package.
##
new_category()
{
    cat<<EOF
Hi,

     A new category (${ARCH_CATEGORY}) has been created
 in the archive ${ARCH_ARCHIVE}.

 regards,

 The Arch Archive Bot

EOF
}

##
## This helper function generates the body of the optional
## notification sent when a new branch is created. This may be
## used to send announcements of new revisions to subscribers of the
## package.
##
new_branch()
{
    cat<<EOF
Hi,

     A new category (${ARCH_BRANCH}) has been created
 in the archive ${ARCH_ARCHIVE}.

 regards,

 The Arch Archive Bot

EOF
}

##
## This helper function generates the body of the optional
## notification sent when a new branch is created.This may be
## used to send announcements of new revisions to subscribers of the
## package.
##
new_revision()
{
    changes=$($CMD cat-archive-log "${ARCH_ARCHIVE}/${ARCH_REVISION}" | cl_entry )

    cat<<EOF
Hi,

     A new category (${ARCH_BRANCH}) has been created
 in the archive ${ARCH_ARCHIVE}.

 regards,

 The Arch Archive Bot
===================================================================
$changes

EOF
}


##
## This is the big switch where most of the real work gets done.  We
## look at ARCH_ACTION, and act accordingly,
##
case "${ARCH_ACTION}" in
    commit | import)
        ##
        ## This is where we do most of the interesting things, since
        ## the repository is usually changed by commits and imports
        ## (which is really just the initial commit).
        ##
	ARCH_CATEGORY="$($CMD parse-package-name --category $ARCH_REVISION)";
	ARCH_BRANCH="$($CMD parse-package-name --branch $ARCH_REVISION)";
	ARCH_VERSION="$($CMD parse-package-name --vsn $ARCH_REVISION)";
	ARCH_BRANCH="$($CMD parse-package-name --branch $ARCH_REVISION)";
        limit=$($CMD parse-package-name --package-version $ARCH_REVISION)
	patch=${ARCH_PATCH##*-};

        ##
        ## Do things only for some of the repositories
        ##
	case "${ARCH_ARCHIVE}" in
	    srivasta@debian.org--lenny|srivasta@debian.org--etch|srivasta@debian.org--20[0-9][0-9]-selinux|srivasta@debian.org--20[0-9][0-9]-primary)
                ##
                ## If any changes are made to my public archives
                ## (Debian, selinux, and a couple of others), cache
                ## every $CACHE_EVERY revisions (like once every 20 or
                ## so); and uncache the previously cached version.
                ## This helps peopletrying to check out my stuff; at
                ## most they have to go get $CACHE_EVERY patches from
                ## the last cached revision.
                ##
		library=$($CMD my-revision-library)
                ##
                ## Do not create a cache for a package called test
                ##
	        if [ "${ARCH_CATEGORY}" != "test" ]; then
		    if [ ${patch:-0} -gt 0 ]; then
		        k=$(( $patch % $CACHE_EVERY ));
		        if [ $k -eq 0 ]; then
			    echo $CMD cacherev "${ARCH_ARCHIVE}"
			    $CMD cacherev "${ARCH_ARCHIVE}"
                            ##
                            ## Remove older cached versions, keeping
                            ## two cached versions in place.
                            ##
			    if [ $patch > $(( $CACHE_EVERY + $CACHE_EVERY )) ]; then
			        j=$(( $patch - $CACHE_EVERY - $CACHE_EVERY ));
                                l=$(( $j % $CACHE_EVERY ));
                                if [ $l -eq 0 ]; then
			            echo $CMD uncacherev \
                                        "${ARCH_ARCHIVE}/${ARCH_CATEGORY}--${ARCH_BRANCH}--${ARCH_VERSION}--patch-$j"
			            $CMD uncacherev      \
                                        "${ARCH_ARCHIVE}/${ARCH_CATEGORY}--${ARCH_BRANCH}--${ARCH_VERSION}--patch-$j"
			            $CMD uncacherev      \
                                        "${ARCH_ARCHIVE}-MIRROR/${ARCH_CATEGORY}--${ARCH_BRANCH}--${ARCH_VERSION}--patch-$j"
                                fi
			    fi
		        fi
		    fi
	        fi

                ##
                ## Now, if the category matches one of my packages,
                ## look to see if any bugs have been closed in this
                ## commit, and, if so, send the log to the bug, and
                ## tag it fixed.
                ##
                update_bug;

	        ;;
            srivasta@golden-gryphon.com--imin)
                ##
                ## This is an ikiwiki commit. Make sure we update the
                ## checkout of the wiki on the webserver.
                ##
                case "${ARCH_CATEGORY}" in
                    manoj)
                        if [ "${ARCH_BRANCH}" = "publish" ]; then
                            ## Ladon is the server hostig the wiki
			    hookLog "Update wiki pages."
                            (ssh ladon bin/update-wiki > $HOME/var/log/wiki.log 2>&1 )&
                        fi
                        ;;
                    *)

                esac
	esac

        ##
        ## The rest is stuff we do for all the archives.
        ##
        ## If we are committing to an archive for which we have a
        ## corresponding -MIRROR defined, update the mirror now, and
        ## tell the human what is going on, since it can take time.
        ##
        if [ -f "${HOME}/.arch-params/=locations/${ARCH_ARCHIVE}-MIRROR" ]; then
	    if [ "${ARCH_CATEGORY}--${ARCH_BRANCH}" != "ikiwiki--upstream" ]; then
                hookLog "Replicating $ARCH_ARCHIVE with limit $limit"
                update_mirror "${ARCH_ARCHIVE}-MIRROR"
	    else
		hookLog "Not mirroring ikiwiki--upstream"
	    fi
        else
            hookLog "Not mirroring $ARCH_ARCHIVE"
        fi

        ##
        ## Special handling for Debian packages.
        ##
        for package in $PACKAGES; do
            if [ "$ARCH_CATEGORY" = "$package" ]; then
                ##
                ## Send full logs via mail to packages.qa.debian.org
                ## for the commit. People can subscribe to a mailing
                ## list setup for each package to get commit logs, if
                ## they so desire.
                ##
                hookLog "Sending notice of ${ARCH_REVISION} to ${package}_cvs@packages.qa.debian.org"
                $CMD cat-log "${ARCH_REVISION}" | \
                    sendmail_wrapper -s "Changes to archive ${ARCH_REVISION}" \
                    ${package}_cvs@packages.qa.debian.org;

                break;
            fi
            if [ "$ARCH_CATEGORY" = "debian-dir" ] &&
                [ "$ARCH_BRANCH" = "$package" ]; then
                ##
                ## While not committing the package, we are committing
                ## the ./debian directory associated with the package,
                ## so again, send in the commit log to the mailing
                ## list.
                ##
                hookLog "Sending notice of ${ARCH_REVISION} to ${package}_cvs@packages.qa.debian.org"
                $CMD cat-log "${ARCH_REVISION}" | \
                    sendmail_wrapper -s "Changes to archive ${ARCH_REVISION}" \
                    ${package}_cvs@packages.qa.debian.org;
                ##
                ## Arch has the concept of a grab file, and people can
                ## get all the components of a software package by
                ## just feeding arch either the grab file (either
                ## locally, or via a http URL). With this, we make
                ## sure we create the config and grab files, and
                ## upload it to a public location mentioned in
                ## ./debian/control for all my packages.
                ##
                (${HOME}/bin/arch_create_config -p "$package";
                    ${HOME}/bin/arch_upload_grab  $package; )
                break;
            fi
        done
        case "$ARCH_ARCHIVE" in
            "debian-policy@lists.debian.org--lenny"|"debian-policy@lists.debian.org--etch")
                ##
                ## For the Debian policy commits, also send mail to the
                ## policy list with full commit logs. This is a group
                ## maintained package, so changes to this are
                ## disseminated slightly more volubly.
                ##
                hookLog "Sending notice of ${ARCH_REVISION} to debian-policy@lists.debian.org"
                $CMD cat-log "${ARCH_REVISION}" | \
                    sendmail_wrapper -s "Changes to archive ${ARCH_REVISION}" \
                    debian-policy@lists.debian.org;
                ;;
            *)
                ##
                ## a no-op. If any other packages need special
                ## actions, they can go above.
                ##
                : echo ""
        esac

        ;;
    find-pristine|make-pristine|make-tmp-pristine)
        ##
        ## a no-op.
        ##
        : echo ""
	;;
    find-cached-revision)
       ##
       ## Whenever we try to find a revision, add it to our local sparse
       ## cache library.
       ##
	update_library;
	;;

    find-archive)
        ##
        ## Hmm. Why is this here?
        ##
        $CMD-find-archive "$ARCH_ARCHIVE"
        exit $?
        ;;
    make-category)
        case "$ARCH_ARCHIVE" in
            "debian-policy@lists.debian.org--lenny"|"debian-policy@lists.debian.org--etch")
                ##
                ## Since Debian policy is a group maintained package,
                ## any new categories should be made very public.
                ## Send mail to the policy mailing lists.
                ##
                hookLog "Sending notice of new category to debian-policy@lists.debian.org"
                new_category | \
                    sendmail_wrapper -s "New category $ARCH_CATEGORY in archive $ARCH_ARCHIVE" \
                debian-policy@lists.debian.org
                ;;
            *)
                ##
                ## Or else, send a mail for archival purposes.
                ##
                hookLog "Sending notice of ${ARCH_CATEGORY} to $MAILTO"
                new_category | \
                    sendmail_wrapper -s "New category $ARCH_CATEGORY in archive $ARCH_ARCHIVE" \
                    $MAILTO
                ;;
        esac
        ;;
    make-branch)
        case "$ARCH_ARCHIVE" in
            "debian-policy@lists.debian.org--lenny"|"debian-policy@lists.debian.org--etch")
                ##
                ## Since Debian policy is a group maintained package,
                ## any new branches should be made very public.
                ## Send mail to the policy mailing lists.
                ##
                hookLog "Sending notice of ${ARCH_BRANCH} to debian-policy@lists.debian.org"
                new_branch  | \
                    sendmail_wrapper -s "New branch ${ARCH_BRANCH} in archive ${ARCH_ARCHIVE}"\
                    debian-policy@lists.debian.org
                ;;
            *)
                ##
                ## Or else, send a mail for archival purposes.
                ##
                hookLog "Sending notice of ${ARCH_BRANCH%%--*} to $MAILTO"
                new_branch | \
                    sendmail_wrapper -s "New branch ${ARCH_BRANCH} in archive $ARCH_ARCHIVE" \
                    $MAILTO
                ;;
        esac
        ;;
    make-version)
        case "$ARCH_ARCHIVE" in
            "debian-policy@lists.debian.org--lenny"|"debian-policy@lists.debian.org--etch")
                ##
                ## Since Debian policy is a group maintained package,
                ## any new versions should be made very public.
                ## Send mail to the policy mailing lists.
                ##
                hookLog "Sending notice of ${ARCH_VERSION} to debian-policy@lists.debian.org"
                new_version | \
                    sendmail_wrapper -s "New vesion ${ARCH_VERSION} in archive ${ARCH_ARCHIVE}" \
                     debian-policy@lists.debian.org
                ;;
            *)
                ##
                ## a no-op. I don't want an email for every version.
                ##
                : echo ""
        esac
        ;;
    *)
        ##
        ## a no-op. I don't want an email for every version.
        ##
        : echo ""

esac

exit 0;


# update_rsync()
# {
#     local TMPD="$(mktemp -q -d $HOME/arch/ARCH/,rsync-tmp.XXXXXX)" || return 1

#     $CMD get --silent --no-pristine yaboot--devel--1.3 "${TMPD}/yaboot" && \
# 	(cd "${TMPD}/yaboot" && setftime --restore-all 0arch-timestamps0)
#     if [ $? -ne 0 ] ; then
# 	rm -rf "$TMPD"
# 	return 2
#     fi

#     $CMD get --silent --no-pristine yaboot--devel--1.99 "${TMPD}/yaboot-devel" && \
# 	(cd "${TMPD}/yaboot-devel" && $CMD buildcfg --no-pristines libs > /dev/null) && \
# 	ln -sf ../../COPYING "${TMPD}/yaboot-devel/lib/libc/COPYING" && \
# 	(cd "${TMPD}/yaboot-devel" && setftime --restore-all 0arch-timestamps0) && \
# 	(cd "${TMPD}/yaboot-devel/lib/libc" && setftime --restore-all 0arch-timestamps0)
#     if [ $? -ne 0 ] ; then
# 	rm -rf "$TMPD"
# 	return 3
#     fi

#     (cd "$TMPD/yaboot" && \
# 	rsync -aqz --delete --exclude=.arch-ids --exclude={arch} --exclude=0arch-timestamps0 \
# 	      --password-file="${HOME}/secure/rsync" . ash::yaboot-eb-rw)
#     if [ $? -ne 0 ] ; then
# 	rm -rf "$TMPD"
# 	return 4
#     fi

#     (cd "$TMPD/yaboot-devel" && \
# 	rsync -aqz --delete --exclude=.arch-ids --exclude={arch} --exclude=0arch-timestamps0 \
# 	      --password-file="${HOME}/secure/rsync" . ash::yaboot-devel-eb-rw)
#     if [ $? -ne 0 ] ; then
# 	rm -rf "$TMPD"
# 	return 5
#     fi

#     rm -rf "$TMPD" || return 6
# }