#!/bin/bash APP_SVNID='$HeadURL$ $LastChangedRevision$' . $(ade-config ade_share_prefix)/include/ade.sh || { echo "${0##*/}: INTERNAL ERROR: failed to load ade.sh" >&2; exit 3; } ADEGMT_DEFINED_ERRORS=( "KEY=ADEGMT_ERR_MISC; FMT=\"%s\"" "KEY=ADEGMT_ERR_ACCESS; FMT=\"%s: can't %s\"" "KEY=ADEGMT_ERR_OS; FMT=\"%s: failed\"" "KEY=ADEGMT_ERR_CONVERT; FMT=\"%s: couldn't convert from %s to %s\"" ) adegmt() { local ERRSTACK_REF="$1" local OPTVAL LISTPATHS RC TEMP ERRSTACK_REF local -a DOLLARAT # Shift off error stack reference. shift ########################################################################### # # SET ADE OPTIONS # ########################################################################### # Register application-specific errors ade_register_error_types ADEGMT_DEFINED_ERRORS ########################################################################### # # PROCESS OPTIONS # ########################################################################### # Defaults for options OPT_MODE=get # Register adegmt's options ade_register_options "$ERRSTACK_REF" -o l --longoptions=list-templates --callback-template="handle_option_%s" || return $? ade_set_callbacks "$ERRSTACK_REF" adegmt_usage_help adegmt_version adegmt_paths || return $? # Process options ade_process_options "$ERRSTACK_REF" NEW_DOLLAR_AT "$@" || return $? set -- "${NEW_DOLLAR_AT[@]}" ########################################################################## # # ARGUMENT PROCESSING # ########################################################################## case $OPT_MODE in get) get "$ERRSTACK_REF" "$@" || return $? ;; list) list "$ERRSTACK_REF" "$@" || return $? ;; esac return $ADE_OK } adegmt_usage_help() { local ERRSTACK_REF="$1"; shift local USAGE_TEXT_SHORT_REF="$1"; shift local USAGE_TEXT_LONG_REF="$1"; shift eval "$USAGE_TEXT_SHORT_REF=\" [ ... ]\"" eval "$USAGE_TEXT_LONG_REF=\"\ -l | --list-templates list template modules\ \"" return $ADE_OK } adegmt_paths() { local ERRSTACK_REF="$1"; shift local PATHLIST_REF=$1; shift eval "$PATHLIST_REF=\"\ \"" return $ADE_OK } adegmt_version() { local ERRSTACK_REF="$1"; shift local VERSION_REF=$1; shift ade_extract_version "$ERRSTACK_REF" "$APP_SVNID" "$VERSION_REF" return $ADE_OK } handle_option_l() { handle_option_list_templates "$@" } handle_option_list_templates() { OPT_MODE=list } get() { local ERRSTACK_REF="$1"; shift [ "X$2" != X ] || ade_show_bad_usage "$ERRSTACK_REF" TPLMOD_NAME="$1" shift NEWMOD_RELPATH="$1" shift NEWMOD_CMPT_RELPATHS="$@" # Guts # Get absolute path of template module. TPLMOD_SEARCHPATH="$(ade-config ade_share_prefix)/templates" ade_debug "$ERRSTACK_REF" 4 "main: TPLMOD_SEARCHPATH=$TPLMOD_SEARCHPATH" FOUND=false for DIR in $TPLMOD_SEARCHPATH; do [ ! -d $DIR/$TPLMOD_NAME ] || { FOUND=true; break; } done $FOUND || { ade_error "$ERRSTACK_REF" ADEGMT_ERR_ACCESS "$TPLMOD_NAME" "find" return $ADE_FAIL } TPLMOD_ABSPATH=$DIR/$TPLMOD_NAME # And some useful stuff about the template module LC_TPLMOD_NAME=${TPLMOD_NAME,,} UC_TPLMOD_NAME=${TPLMOD_NAME^^} CL_TPLMOD_NAME=${TPLMOD_NAME^} ade_debug "$ERRSTACK_REF" 4 "main: TPLMOD_ABSPATH=$TPLMOD_ABSPATH, LC_TPLMOD_NAME=$LC_TPLMOD_NAME, UC_TPLMOD_NAME=$UC_TPLMOD_NAME, CL_TPLMOD_NAME=$CL_TPLMOD_NAME" [ ! -e $NEWMOD_RELPATH -a ! -h $NEWMOD_RELPATH ] || { ade_error "$ERRSTACK_REF" ADEGMT_ERR_MISC "$NEWMOD_RELPATH: exists already" return $ADE_FAIL } ade_info "$ERRSTACK_REF" "creating root for new module ..." ade_evaler "$ERRSTACK_REF" "mkdir -p $NEWMOD_RELPATH" # Get absolute path of new module. ade_get_absolute_path "$ERRSTACK_REF" $NEWMOD_RELPATH "" NEWMOD_ABSPATH || { RC=$? ade_error "$ERRSTACK_REF" ADEGMT_ERR_CONVERT "$NEWMOD_RELPATH" "path" "absolute path" return $RC } # And some useful stuff about the new module. NEWMOD_NAME=${NEWMOD_ABSPATH##*/} LC_NEWMOD_NAME=${NEWMOD_NAME,,} UC_NEWMOD_NAME=${NEWMOD_NAME^^} CL_NEWMOD_NAME=${NEWMOD_NAME^} CREATION_YEAR=$(date '+%Y') CREATION_DATE_LONG="$(date '+%d %B %Y')" ade_debug "$ERRSTACK_REF" 4 "main: NEWMOD_ABSPATH=$NEWMOD_ABSPATH, LC_NEWMOD_NAME=$LC_NEWMOD_NAME, UC_NEWMOD_NAME=$UC_NEWMOD_NAME, CL_NEWMOD_NAME=$CL_NEWMOD_NAME, CREATION_YEAR=$CREATION_YEAR, CREATION_DATE_LONG=$CREATION_DATE_LONG" # Get absolute path of transfer module. XFERMOD_ABSPATH=/var/tmp/$PROGNAME.$$.xfer # And some useful stuff about the transfer module. XFERMOD_NAME=$TPLMOD_NAME LC_XFERMOD_NAME=${XFERMOD_NAME,,} UC_XFERMOD_NAME=${XFERMOD_NAME^^} CL_XFERMOD_NAME=${XFERMOD_NAME^} ade_debug "$ERRSTACK_REF" 4 "main: XFERMOD_ABSPATH=$XFERMOD_ABSPATH, LC_XFERMOD_NAME=$LC_XFERMOD_NAME, UC_XFERMOD_NAME=$UC_XFERMOD_NAME, CL_XFERMOD_NAME=$CL_XFERMOD_NAME" ########################################################################### # # Re-map component paths to same format 'find' would output. # ########################################################################### # This will be useful in the remapping process. PWD=$(pwd) # How many have we fixed so far? None. FIXED_NEWMOD_CMPT_RELPATHS= for NEWMOD_CMPT_RELPATH in $NEWMOD_CMPT_RELPATHS; do # If cwd is under the user said something like: # adegmt lxadesh .. somemanpage.1 # from in /man. The second arg (the component) we map to: # ./man/somemanpage.1 if MODSUB=(expr "$PWD" : "$NEWMOD_ABSPATH/\(.*\)"); then ade_debug "$ERRSTACK_REF" 10 "main: run from below modroot (MODSUB=$MODSUB)" FIXED_NEWMOD_CMPT_RELPATH="./$MODSUB/$NEWMOD_CMPT_RELPATH" # If cwd is above then the user said something like: # adegmt mymodules/xyz mymodules/xyz/man/somemanpage.1 # from above mymodules. The second arg (the component) we map to: # ./man/somemanpage.1 elif MODSUP=$(expr "$NEWMOD_ABSPATH" : "$PWD/\(.*\)"); then ade_debug "$ERRSTACK_REF" 10 "main: run from above modroot (MODSUP=$MODSUP)" FIXED_NEWMOD_CMPT_RELPATH="./$(expr "$NEWMOD_CMPT_RELPATH" : "$MODSUP/\\(.*\\)")" # And if we are *in* then the user said something like: # adegmt . man/somemanpage.1 # from in . The second arg (the component) we map to: # ./man/somemanpage.1 elif MODEQ=$(expr "$NEWMOD_ABSPATH" : "$PWD\$") > /dev/null; then ade_debug "$ERRSTACK_REF" 10 "main: run from in modroot (MODEQ=$MODEQ)" FIXED_NEWMOD_CMPT_RELPATH="./$NEWMOD_CMPT_RELPATH" # Otherwise I have no idea what happened. This might be possible, # but I've not come across it yet. else ade_internal "$ERRSTACK_REF" "confused" fi # A component of './' should be ignored. This arises when the # user specifies a component that matches the root of the # module. e.g.: # adegmt .. .. # which means "I'm in subdirectory of the modroot (e.g. 'bin') # and I want everything that belongs under the parent directory." [ $FIXED_NEWMOD_CMPT_RELPATH = ./ ] && continue # Trailing '/.' should be stripped too. This arises when the # user specifies '.' for a component. After the stripping, this # will leave './bin' if the user was in the bin directory, but # will leave '.' if the user was in the top directory: but this # is acceptable: it matches what 'find' produced, and will therefore # be accepted correctly. FIXED_NEWMOD_CMPT_RELPATH=$(echo $FIXED_NEWMOD_CMPT_RELPATH | sed 's/\/\.$//') ade_debug "$ERRSTACK_REF" 4 "main: fixed cmpt=$FIXED_NEWMOD_CMPT_RELPATH" FIXED_NEWMOD_CMPT_RELPATHS="$FIXED_NEWMOD_CMPT_RELPATHS $FIXED_NEWMOD_CMPT_RELPATH" done # Stick it all back in the original variable (it has a nicer name). NEWMOD_CMPT_RELPATHS="$FIXED_NEWMOD_CMPT_RELPATHS" # Create transfer module root [ ! -e $XFERMOD_ABSPATH -a ! -h $XFERMOD_ABSPATH ] || { ade_error "$ERRSTACK_REF" ADEGMT_ERR_MISC "$XFERMOD_ABSPATH: exists already" return $ADE_FAIL } ade_register_temp_file "$ERRSTACK_REF" $XFERMOD_ABSPATH mkdir -p $XFERMOD_ABSPATH || { ade_error "$ERRSTACK_REF" ADEGMT_ERR_ACCESS "$XFERMOD_ABSPATH" "create" return $ADE_FAIL } # Copy the whole of the template module to the transfer module root. ( cd $TPLMOD_ABSPATH && find . -depth | cpio -pudm $XFERMOD_ABSPATH 2>/dev/null ) || { ade_error "$ERRSTACK_REF" ADEGMT_ERR_OS "cpio" return $ADE_FAIL } # Create sorted list of module components. XFERMOD_FSITEMS_LIST=/var/tmp/$PROGNAME.$$.list ade_register_temp_file "$ERRSTACK_REF" $XFERMOD_FSITEMS_LIST ( cd $XFERMOD_ABSPATH && find . ) | sort > $XFERMOD_FSITEMS_LIST # Copy over what user specified or all if nothing specified. # To flag a 'nothing copied' error. ACCEPTED_SOMETHING=false while read XFERMOD_FSITEM; do # Skip .svn directories expr "$XFERMOD_FSITEM" : '.*/\.svn$' > /dev/null && continue # Skip things under .svn directories expr "$XFERMOD_FSITEM" : '.*/\.svn/.*' > /dev/null && continue # Work out target name NEWMOD_FSITEM=$(echo $XFERMOD_FSITEM | sed \ -e "s/\/$LC_XFERMOD_NAME/\/$LC_NEWMOD_NAME/g" \ -e "s/\/$UC_XFERMOD_NAME/\/$UC_NEWMOD_NAME/g" \ -e "s/\/$CL_XFERMOD_NAME/\/$CL_NEWMOD_NAME/g") # By default assume no match ... ACCEPT=false ade_debug "$ERRSTACK_REF" 10 "main: considering $NEWMOD_FSITEM (NEWMOD_CMPT_RELPATHS=\"$NEWMOD_CMPT_RELPATHS\") ..." # ... and accept it if the user specified nothing ... if [ "X$NEWMOD_CMPT_RELPATHS" = X ]; then ACCEPT=true # ... or if matches what user specified else for NEWMOD_CMPT_RELPATH in $NEWMOD_CMPT_RELPATHS; do # accept precise matches ... if [ $NEWMOD_CMPT_RELPATH = $NEWMOD_FSITEM ]; then ACCEPT=true break # ... and things under precise matches elif expr $NEWMOD_FSITEM : "$NEWMOD_CMPT_RELPATH/" > /dev/null; then ACCEPT=true break fi done fi # Skip to next item if not accepting it. [ $ACCEPT = false ] && continue # Suppress 'nothing copied' error. ACCEPTED_SOMETHING=true ###################################################################### # # Copy item over # ###################################################################### # If (desired) item in transfer module is directory, make directory # in new module. if [ -d $XFERMOD_ABSPATH/$XFERMOD_FSITEM -a ! -h $XFERMOD_ABSPATH/$XFERMOD_FSITEM ]; then ade_debug "$ERRSTACK_REF" 10 "main: creating dir $NEWMOD_FSITEM ..." ade_evaler "$ERRSTACK_REF" "mkdir -p $NEWMOD_ABSPATH/$NEWMOD_FSITEM" # If (desired) item is file, copy with substitions on content # (Substitions on name have already been made.) elif [ -f $XFERMOD_ABSPATH/$XFERMOD_FSITEM -a ! -h $XFERMOD_ABSPATH/$XFERMOD_FSITEM ]; then ade_debug "$ERRSTACK_REF" 10 "main: creating file $NEWMOD_FSITEM ..." ade_evaler "$ERRSTACK_REF" "sed -e \"s/$LC_XFERMOD_NAME/$LC_NEWMOD_NAME/g\" \ -e \"s/$UC_XFERMOD_NAME/$UC_NEWMOD_NAME/g\" \ -e \"s/$CL_XFERMOD_NAME/$CL_NEWMOD_NAME/g\" \ -e \"s/ADE_\APP_TOKEN_CREATION_YEAR/$CREATION_YEAR/g\" \ -e \"s/ADE_\APP_TOKEN_CREATION_DATE_LONG/$CREATION_DATE_LONG/g\" \ < $XFERMOD_ABSPATH/$XFERMOD_FSITEM > \ $NEWMOD_ABSPATH/$NEWMOD_FSITEM" # Copy over execute bit if [ -x $XFERMOD_ABSPATH/$XFERMOD_FSITEM ]; then ade_evaler "$ERRSTACK_REF" "chmod a+x $NEWMOD_ABSPATH/$NEWMOD_FSITEM" fi # If (desired) item is not file or directory, then give up. # (We may handle other cases if they ever become needed; I # guess this is most likely to be symlinks.) else ade_internal "$ERRSTACK_REF" "unknown entity type (XFERMOD_FSITEM=$XFERMOD_FSITEM, NEWMOD_FSITEM=$NEWMOD_FSITEM" fi done < $XFERMOD_FSITEMS_LIST rm -f $XFERMOD_FSITEMS_LIST ade_deregister_temp_file "$ERRSTACK_REF" $XFERMOD_FSITEMS_LIST # We would check that something was actually copied here, but we # need to delete the transfer module first either way, so we'll # do the check in a moment. ########################################################################## # # Tidy up. # ########################################################################## # Remove transfer module. rm -fr $XFERMOD_ABSPATH ade_deregister_temp_file "$ERRSTACK_REF" $XFERMOD_ABSPATH # Here we do that check just mentioned above. [ $ACCEPTED_SOMETHING = false ] && { ade_error "$ERRSTACK_REF" ADEGMT_ERR_MISC "nothing was installed!" return $ADE_FAIL } # yes, of course, it does this anyway, but this is clearer. return $ADE_OK } list() { local ERRSTACK_REF="$1"; shift [ $# = 0 ] || ade_show_bad_usage "$ERRSTACK_REF" for DIR in $(ade-config ade_share_prefix)/templates/*; do [ -d "$DIR" ] || continue DESC=$(grep -rl 'ADEGMT-LIST-HINT: *' $DIR | xargs sed -nr 's/.*ADEGMT-LIST-HINT: *//p') if [ "X$DESC" = X ]; then ade_warning "$ERRSTACK_REF" ADEGMT_ERR_MISC "$DIR: no hint found" continue fi printf "%-12s %s\\n" "${DIR##*/}:" "$DESC" done return $ADE_OK } ade_main adegmt "$@"