#!/bin/bash PROGNAME=`basename $0` VERBOSELEVEL=2 # $HeadURL$ $LastChangedRevision$ ALLDIRS="bin doc sbin man lib include locale" main() { # # Process options # OPT_SIMULATE=false while [ "X$1" != X ]; do case "$1" in -d) VERBOSELEVEL=$2; shift ;; --debug=*) VERBOSELEVEL=${1#*=} ;; -v|--verbose) VERBOSELEVEL=3 ;; -n) OPT_SIMULATE=true ;; -h|--help) usage 0 ;; --simulate) OPT_SIMULATE=true ;; --) shift; break ;; -*) usage ;; *) break ;; esac shift done # # Process arguments # [ "X$1" != X ] || usage PKGROOT=$1 shift for DIR in $*; do expr $DIR : '/' > /dev/null || error "$DIR: not absolute" for ALLDIR in $ALLDIRS; do MATCHED=false if expr "$DIR" : ".*/$ALLDIR\$" > /dev/null; then debug 10 "main: assigning $(uc $ALLDIR)DIR=$DIR ..." eval "$(uc $ALLDIR)DIR=$DIR" MATCHED=true break fi done $MATCHED || error "$DIR: don't know what this is" done # # Sanity checks and derivations # # check package root exists [ -d "$PKGROOT" ] || error "$PKGROOT: no such directory" # check what information is required. for ALLDIR in $ALLDIRS; do eval "FLAG_NEED$(uc $ALLDIR)=false" done # The ls needs to be done as two separate commands because of the # way the output format varies when more than one arg is given. for DIR in `ls $PKGROOT 2>/dev/null` `ls $PKGROOT/share 2>/dev/null`; do # We're interested in the contents of share, not share itself. [ $DIR != share ] || continue MATCHED=false for ALLDIR in $ALLDIRS; do if [ $DIR = $ALLDIR ]; then MATCHED=true break fi done $MATCHED || error "$DIR: you didn't specify where to symlink its contents to" ! eval "\$FLAG_NEED$(uc $DIR)" || error "$DIR: appears to be in two places" eval "FLAG_NEED$(uc $DIR)=true" done # check all required information has been provided. for DIR in $ALLDIRS; do eval "NEED=\$FLAG_NEED$(uc $DIR)" eval "GIVENDIR=\$$(uc $DIR)DIR" debug 10 "main: DIR=$DIR, NEED=$NEED, GIVENDIR=$GIVENDIR" if [ $NEED = true -a "X$GIVENDIR" != X ]; then [ -d $GIVENDIR ] || error "$GIVENDIR: no such directory" elif [ $NEED = false -a "X$GIVENDIR" = X ]; then : elif [ $NEED = true ]; then error "$DIR: target needed but not specified" else warning "$DIR: specified but not needed" fi done if [ -d $PKGROOT/man ]; then MANSUBDIR=man elif [ -d $PKGROOT/share/man ]; then MANSUBDIR=share/man fi if [ -d $PKGROOT/doc ]; then DOCSUBDIR=doc elif [ -d $PKGROOT/share/doc ]; then DOCSUBDIR=share/doc fi LOCALESUBDIR=share/locale BINSUBDIR=bin SBINSUBDIR=sbin INCLUDESUBDIR=include LIBSUBDIR=lib # # Guts # debug 10 "main: BINDIR=$BINDIR, DOCDIR=$DOCDIR, MANDIR=$MANDIR, SBINDIR=$SBINDIR, LIBDIR=$LIBDIR, LOCALEDIR=$LOCALEDIR" if [ "X$BINDIR" != X ]; then info "$PKGROOT/$BINSUBDIR/* --> $BINDIR/ ..." ade_std_shell -n $OPT_SIMULATE "mkdir -p $BINDIR" ade_std_shell -n $OPT_SIMULATE "cd $BINDIR" debug 10 "main: $PKGROOT/$BINSUBDIR contains `ls $PKGROOT/$BINSUBDIR 2>/dev/null | xargs echo`" [ "X`ls $PKGROOT/$BINSUBDIR 2>/dev/null`" = X ] || { ade_std_shell -n $OPT_SIMULATE "rm -f `ls $PKGROOT/$BINSUBDIR | xargs echo`" RELDIR=`ade_fnm_getrelativity $BINDIR $PKGROOT/$BINSUBDIR` || internalerror "ade_fnm_getrelativity failed" debug 10 "main: bin: RELDIR=$RELDIR" ade_std_shell -n $OPT_SIMULATE "ln -s $RELDIR/* ." } fi if [ "X$INCLUDEDIR" != X ]; then info "$PKGROOT/$INCLUDESUBDIR/* --> $INCLUDEDIR/ ..." ade_std_shell -n $OPT_SIMULATE "mkdir -p $INCLUDEDIR" ade_std_shell -n $OPT_SIMULATE "cd $INCLUDEDIR" [ "X`ls $PKGROOT/$INCLUDESUBDIR 2>/dev/null`" = X ] || { ade_std_shell -n $OPT_SIMULATE "rm -f `ls $PKGROOT/$INCLUDESUBDIR | xargs echo`" RELDIR=`ade_fnm_getrelativity $INCLUDEDIR $PKGROOT/$INCLUDESUBDIR` || internalerror "ade_fnm_getrelativity failed" ade_std_shell -n $OPT_SIMULATE "ln -s $RELDIR/* ." } fi if [ "X$MANDIR" != X ]; then info "$PKGROOT/$MANSUBDIR/manX/* --> $MANDIR/manX ..." ade_std_shell -n $OPT_SIMULATE "mkdir -p $MANDIR" ade_std_shell -n $OPT_SIMULATE "cd $MANDIR" for DIR in man1 man2 man3 man4 man5 man6 man7 man8; do ade_std_shell -n $OPT_SIMULATE "mkdir -p $MANDIR/$DIR" ade_std_shell -n $OPT_SIMULATE "cd $MANDIR/$DIR" [ "X`ls $PKGROOT/$MANSUBDIR/$DIR 2>/dev/null`" = X ] || { # need xargs echo to ensure eval is eval'ing: # # rm a b c # # # and not: # # rm a # b # c ade_std_shell -n $OPT_SIMULATE "rm -f `ls $PKGROOT/$MANSUBDIR/$DIR | xargs echo`" RELDIR=`ade_fnm_getrelativity $MANDIR/$DIR $PKGROOT/$MANSUBDIR/$DIR` || internalerror "ade_fnm_getrelativity failed" debug 10 "main: PWD=$(pwd), RELDIR=$RELDIR, ls $RELDIR =$(ls $RELDIR)" ade_std_shell -n $OPT_SIMULATE "ln -s $RELDIR/* ." } done fi if [ "X$LOCALEDIR" != X ]; then info "$PKGROOT/$LOCALESUBDIR///* --> $LOCALEDIR///* ..." ade_std_shell -n $OPT_SIMULATE "mkdir -p $LOCALEDIR" ade_std_shell -n $OPT_SIMULATE "cd $LOCALEDIR" [ "X`ls $PKGROOT/$LOCALESUBDIR 2>/dev/null`" = X ] || { ( cd $PKGROOT/$LOCALESUBDIR && find * -type f ) | while read THING; do ade_std_shell -n $OPT_SIMULATE "rm -f $THING" RELDIR=`ade_fnm_getrelativity $(dirname $LOCALEDIR/$THING) $(dirname $PKGROOT/$LOCALESUBDIR/$THING)` || internalerror "ade_fnm_getrelativity failed" ade_std_shell -n $OPT_SIMULATE "mkdir -p $(dirname $THING)" ade_std_shell -n $OPT_SIMULATE "ln -s $RELDIR/$(basename $THING) $THING" done } fi if [ "X$SBINDIR" != X ]; then info "$PKGROOT/$SBINSUBDIR/* --> $SBINDIR/ ..." ade_std_shell -n $OPT_SIMULATE "mkdir -p $SBINDIR" ade_std_shell -n $OPT_SIMULATE "cd $SBINDIR" [ "X`ls $PKGROOT/$SBINSUBDIR 2>/dev/null`" = X ] || { ade_std_shell -n $OPT_SIMULATE "rm -f `ls $PKGROOT/$SBINSUBDIR | xargs echo`" RELDIR=`ade_fnm_getrelativity $SBINDIR $PKGROOT/$SBINSUBDIR` || internalerror "ade_fnm_getrelativity failed" ade_std_shell -n $OPT_SIMULATE "ln -s $RELDIR/* ." } fi if [ "X$LIBDIR" != X ]; then info "$PKGROOT/$LIBSUBDIR/* --> $LIBDIR/ ..." ade_std_shell -n $OPT_SIMULATE "mkdir -p $LIBDIR" ade_std_shell -n $OPT_SIMULATE "cd $LIBDIR" [ "X`ls $PKGROOT/$LIBSUBDIR 2>/dev/null`" = X ] || { ade_std_shell -n $OPT_SIMULATE "rm -f `ls $PKGROOT/$LIBSUBDIR | xargs echo`" RELDIR=`ade_fnm_getrelativity $LIBDIR $PKGROOT/$LIBSUBDIR` || internalerror "ade_fnm_getrelativity failed" ade_std_shell -n $OPT_SIMULATE "ln -s $RELDIR/* ." } fi if [ "X$DOCDIR" != X ]; then info "$PKGROOT/$DOCSUBDIR/* --> $DOCDIR/ ..." ade_std_shell -n $OPT_SIMULATE "mkdir -p $DOCDIR" ade_std_shell -n $OPT_SIMULATE "cd $DOCDIR" [ "X`ls $PKGROOT/$DOCSUBDIR 2>/dev/null`" = X ] || { ade_std_shell -n $OPT_SIMULATE "rm -f `ls $PKGROOT/$DOCSUBDIR | xargs echo`" RELDIR=`ade_fnm_getrelativity $DOCDIR $PKGROOT/$DOCSUBDIR` || internalerror "ade_fnm_getrelativity failed" ade_std_shell -n $OPT_SIMULATE "ln -s $RELDIR/* ." } fi } usage() { local RC T RC=${1:-1} { # Construct a list of optional arguments for ALLDIR in $ALLDIRS; do [ "X$T" = X ] || T="$T | " T="$T<${ALLDIR}dir>" done echo "Usage: $PROGNAME [ ] [ $T ] ..." echo echo "Options: -v | --verbose be verbose" echo " -d | --debug= be very verbose" echo " -h | --help show this text" echo " -n | --simulate do nothing for real" echo } | if [ $RC = 0 ]; then cat else cat >&2 fi exit $RC } uc() { echo "$1" | tr '[a-z]' '[A-Z]' } internalerror() { echo "$PROGNAME: INTERNAL ERROR: $1" >&2 exit 1 } error() { echo "$PROGNAME: ERROR: $1" >&2 exit 1 } warning() { echo "$PROGNAME: WARNING: $1" >&2 } info() { [ $VERBOSELEVEL -lt 3 ] || { echo "$PROGNAME: INFO: $1" >&2; } } debug() { [ $VERBOSELEVEL -lt $1 ] || { echo "$PROGNAME: DEBUG[$1]: $2" >&2; } } # ADE interface support functions for functions stolen from ADE below. ade_msg_debug() { debug "$@" } ade_msg_warning() { warning "$@" } ade_msg_internalerror() { internalerror "$@" } # Functions stolen from ADE (can get out of date wrt ADE) ade_std_shell() { local SIMULATE CMD SUBSHELL PROMPT SHELLCMD # Default values for options SIMULATE=false SUBSHELL=false PROMPT= SHELLCMD=${SHELL:-/bin/bash} # Process options while [ "X$1" != X ]; do case $1 in -n) SIMULATE=$2 shift ;; -c) SUBSHELL=true ;; -s) SHELLCMD="$2" shift ;; -p) PROMPT="$2" shift ;; -*) ade_msg_internalerror "ade_std_shell: bad option '$1'" ;; *) break ;; esac shift done # Read arguments CMD="$1" # handle all combinations of simulation, subshells, etc. if [ "X$CMD" = X -a $SIMULATE = true ]; then ade_msg_warning "no interactive shell started, as mode is simulated" elif [ "X$CMD" = X ]; then if expr $SHELLCMD : '.*/bash$'; then PS1=$PROMPT $SHELLCMD --norc else PS1=$PROMPT $SHELLCMD fi # In the special case of the 'cd' command we run it even if in simulation elif [ $SIMULATE = true -a $SUBSHELL = false -a "X${CMD%% *}" = Xcd ]; then echo "$CMD" | sed 's/[ ][ ]*/ /g' [ "X`sh -c \"$CMD\" 2>&1`" = X ] || warning "expect next cd to fail" eval "$CMD" elif [ $SIMULATE = true ]; then echo "$CMD" | sed 's/[ ][ ]*/ /g' elif [ $SUBSHELL = true ]; then $SHELLCMD -c "$CMD" else eval "$CMD" fi } ade_fnm_getrelativity() { # Usage: path_from # Desc: calculates a relative path from to local SRC_DIR DST_DIR SRC_LIST DIR REL_PATH DST_LIST SRC_DIR=$1 DST_DIR=$2 ade_msg_debug 60 "ade_fnm_getrelativity: original paths $SRC_DIR and $DST_DIR" { expr $SRC_DIR : '\/' > /dev/null && expr $DST_DIR : '\/' > /dev/null; } || ade_msg_internalerror "Usage: ade_fnm_getrelativity (SRC_DIR=$SRC_DIR, DST_DIR=$DST_DIR)" SRC_DIR=`echo $SRC_DIR | sed 's/^\///'` DST_DIR=`echo $DST_DIR | sed 's/^\///'` ade_msg_debug 60 "ade_fnm_getrelativity: leading slash removed paths $SRC_DIR and $DST_DIR" SRC_LIST=`echo $SRC_DIR | sed 's/\// /g'` for DIR in $SRC_LIST; do ade_msg_debug 60 "ade_fnm_getrelativity: checking if paths start with $DIR ..." expr $DST_DIR : "$DIR/" > /dev/null || expr $DST_DIR : "$DIR\$" > /dev/null || break SRC_DIR=`echo $SRC_DIR | sed "s/^\\\\($DIR\\\\/\\\\|$DIR\\\$\\\\)//"` DST_DIR=`echo $DST_DIR | sed "s/^\\\\($DIR\\\\/\\\\|$DIR\\\$\\\\)//"` done ade_msg_debug 60 "ade_fnm_getrelativity: reduced paths are '$SRC_DIR' and '$DST_DIR'" if [ "X$SRC_DIR" = X -a "X$DST_DIR" = X ]; then REL_PATH=. else REL_PATH=`echo $SRC_DIR | sed 's/[^/][^/]*/../g'`/$DST_DIR fi ade_msg_debug 60 "ade_fnm_getrelativity: returning $REL_PATH" echo $REL_PATH return 0 } main "$@"