#!/bin/bash
#---------------------------------------------------------------------
##
##=head1 SYNOPSIS
##
## gaze - view sorcery spell management information
## (gaze into the crystal ball)
##
##=head1 DESCRIPTION
##
## ...
##
##=head1 COPYRIGHT
##
## First version of gaze written & copyrighted 2001 by Brian Peterson
## 
## Current version contains none of Brian Peterson's code and is 
## Copyright 2001 by Kyle Sallee
##
## Other additions/corrections Copyright 2002 by the Source Mage Team
##
##=head1 FUNCTIONS
##
##=over 4
##
#---------------------------------------------------------------------


help() {
cat << EOF

Invoke gaze with desired command followed by arguments.
Please note that anything in brackets [] is optional.

Command		Arguments	Description

-q		<empty>		disable human style output

alien		<empty>		Discover untracked files.
from		path/file	Discover what installed a file.

search		"phrase"	Searches for "phrase" in the long and 
				  short spell descriptions and in the spell name.
search      -name  "phrase" Searches for "phrase" in the spell name.
search      -short "phrase" Searches for "phrase" in the short spell 
                            descriptions

service		port|acronym	Displays spells that provide that service.
provides	feature 	Displays spells that provide the feature.

what		spell		Print the spell's description.
short           spell           Print the spell's short description.
where		spell		Print the spell's section.
website | url	spell		Print the spell's website.
install		spell		View an install log.
installed	[spell]		View/query installed spells.
version		spell		View version of spell installed, and version in 
				the grimoire.
license		spell [spell]	View the license of the given spell(s)
license		section [section]	View the licenses of spells in the given
					section(s)
license		license [license]	View information about the given license(s).
compile		spell		View a compile log.
sources		spell		List the source files for a spell.
history		spell		Show history for a spell.

sum			[spell]		Prints checksums.
md5sum		[spell]		Prints md5sums.
export					Make snapshot of box's configuration.
import		snapshot	Restore snapshot.

section		[section]	List grimoire sections.
maintainer	[section]	See who is the maintainer for a section
grimoire	[grimoire]	View a text listing of all grimoires.
                        Or of the specified grimoire.
grimoires				View list of installed grimoires (Grimoire names only).
html	[-s]	[grimoire]	View a html listing of all grimoires.
                        Or of the specified grimoire.
                        Additionally displays links to the source files 
                        when -s is given.

newer		20020521	Show available spells newer than May 21, 2002.
older		20010521	Show spells installed before May 21, 2001.

prune		<empty>		Removes all old sources from $SOURCE_CACHE
				  and removes all old backups from 
				  $INSTALL_CACHE.

voyeur		[delay or spell]  
				Peek into spell compilation.

pam		<empty>		Display installed or held spells that are
				  Linux-PAM aware.


orphans		<empty>		Display installed spells that have no
				  explicit dependencies on them.

depends        spell [level]       Displays the spells that explicitly or
                   recursively depend on this spell, up to $level levels.
                    $level is kinda infinity if omitted.

dependencies    spell [level]     Displays the spells $spell explicitly or 
                        recursively depends on, up to $level levels.
                        $level is kinda infinity if omitted.

\$SPELL_SCRIPT	spell	will print the spell script for that spell.

install-queue	<empty>		View the install queue

remove-queue	<empty>		View the remove queue

checkmd5s       spell/section/<empty> Print a md5 check of spells
EOF
}
#' Just ignore this... it's so my poor syntax hilighting works.'

export_snapshot()  {

  SOURCE_DIRECTORY=$BUILD_DIRECTORY/snapshot
  mk_source_dir          $SOURCE_DIRECTORY
  cp  -a  /etc           $SOURCE_DIRECTORY
  cp  -a  $CONFIG_CACHE  $SOURCE_DIRECTORY

  for  LINE  in  `cat  $SPELL_STATUS`;  do
    SPELL=`echo  $LINE  |  cut  -d  :  -f1`
     STATUS=`echo  $LINE  |  cut  -d  :  -f2`
    if  [  "$STATUS"  ==  "installed"  ];  then
      echo  $SPELL  >>  /usr/src/snapshot/install
    fi
  done

  SNAPSHOT="/root/snapshot-$HOSTNAME-`date  -u  +%Y%m%d`.tar$EXTENSION"

  cd  $BUILD_DIRECTORY
  if  [  -n  "$EXTENSION"  ];  then
    tar    -c  snapshot     |
    $COMPRESSBIN      >  $SNAPSHOT
  else
    tar  -cf  $SNAPSHOT  snapshot
  fi
  
  rm_source_dir          $SOURCE_DIRECTORY
  echo  "$SNAPSHOT created."

}


import_snapshot()  {

          SNAPSHOT=$1
  SOURCE_DIRECTORY=$BUILD_DIRECTORY/snapshot

  if  [  -f  "$1"  ];  then

    cd  $BUILD_DIRECTORY
    mk_source_dir          $SOURCE_DIRECTORY

    if  [  -n  "$EXTENSION"  ];  then
      $COMPRESSBIN -dc $SNAPSHOT  |  tar  -x
    else
      tar  -xf  $SNAPSHOT
    fi

    cd  $SOURCE_DIRECTORY

    for  LINE  in  `cat  install`;  do
      push_install_queue  $LINE
    done
    report  $INSTALL_QUEUE  "Install Queue"

    cp  -ai  local  /etc/sorcery
    cp  -ai  etc    /

    cd  /
    rm_source_dir  $SOURCE_DIRECTORY

  else

    message  "Unable to find snapshot  \"$SNAPSHOT\""
    false

  fi

}


checksum()      { for FILE in `cat $1 | files`; do sum -s  $FILE; done; }
md5sum_files()  { for FILE in `cat $1 | files`; do md5sum  "$FILE"; done; }


alien()  {

  message  "In a few minutes I will print files found on this disk"
  message  "that were not installed by sorcery.  This is not a"
  message  "security feature!  Files could still be lurking"
  message  "undetected on this box."

  rm    -f  /tmp/gaze.found
  rm    -f  /tmp/gaze.known

  message  "Discovering ambient files..."
  find  $TRACKED  |  files  |  filter  "$EXCLUDED"  |  sort  >/tmp/gaze.found
 
  message  "Discovering installed files..."
  cat  $INSTALL_LOGS/*  /etc/sorcery/update/sorcery-${SORCERY_BRANCH}.log  |  files  |  sort  >  /tmp/gaze.known

  diff  -B  -a  -d  /tmp/gaze.found  /tmp/gaze.known  |
  grep  -v  "^> "                                     |
  grep      "^< "                                     |
  cut  -c  3-                                         |
  filter  "$PROTECTED"

  rm  -f  /tmp/gaze.found
  rm  -f  /tmp/gaze.known

}


gaze_catalog()  {

  local grimoire

  if [[ $# -gt 0 ]]; then
        grimoire=$(codex_find_grimoire_by_name $1)
        if [[ $? != 0 ]]; then
            echo "No such grimoire $1"
            exit 1;
        fi  
  fi

  echo  "Sorcery Grimoire for `date  -u`"

  if [ $grimoire ]; then
        echo "Grimoire: " $(basename $grimoire)
  else
        echo "Grimoires: " $(codex_get_all_grimoires | get_basenames)
  fi

  ((  COUNT=0  ))

  for  SECTION  in  `codex_get_all_sections $grimoire`;  do
    echo 
    echo  "-------------------------------------------------"
    echo  "SECTION:  $(  basename  $SECTION  )"  
    echo  "-------------------------------------------------"
    for  spell  in  `codex_get_spells $SECTION`;  do
       echo `basename $spell`
      ((  COUNT++  ))
    done
  done

  echo
  echo  "Total spells:  $COUNT"

}


gaze_catalog_html()  {

  local grimoire COLS=4

  if [[ $1 == "-s" ]]; then
        shift;
        (( COLS++ ))
  fi
    
  if [[ $# -gt 0 ]]; then
        grimoire=$(codex_find_grimoire_by_name $1)
        if [[ $? != 0 ]]; then
            echo "No such grimoire $1"
            exit 1;
        fi
  fi

  echo  "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 STRICT//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
  echo  "<html xmlns=\"http://www.w3.org/1999/xhtml\">"
  echo  "<head>"
  echo  "<title>Sorcery Grimoires for `date  -u`</title>"
  echo  "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\" />"
  echo  "<style type=\"text/css\" media=\"all\"> <!--"
  echo  "body"
  echo  "{"
  echo  "background: white;"
  echo  "color: black;"
  echo  "font-family: Verdana, Arial, Helvetica, sans-serif;"
  echo  "font-size: 10pt;"
  echo  "margin:0px;"
  echo "}"
  echo ""
  echo "h1"
  echo "{"
  echo "background: white;"
  echo "color: green;"
  echo "text-align: center;"
  echo "font-family: Verdana, Arial, Helvetica, sans-serif;"
  echo "font-size: 14pt; "
  echo "}"

  echo "h2"
  echo "{"
  echo "background: white;"
  echo "color: green;"
  echo "text-align: center;"
  echo "font-family: Verdana, Arial, Helvetica, sans-serif;"
  echo "font-size: 12pt; "
  echo "}"

  echo "table"
  echo "{"
  echo "width: 100%;"
  echo "border-style: solid;"
  echo "border-color: black;"
  echo "border-width: 2px;"
  echo "}"

  echo "th"
  echo "{"
  echo "vertical-align: top;"
  echo "text-align: left;"
  echo "background: white;"
  echo "color: black;"
  echo "border-style: solid;"
  echo "border-color: black;"
  echo "border-width: 2px;"
  echo "font-size:12pt;"
  echo "}"

  echo "td"
  echo "{"
  echo "background: white;"
  echo "color: black;"
  echo "vertical-align: top; "
  echo "text-align: left;"
  echo "border-style: solid;"
  echo "border-color: black;"
  echo "border-width: 2px;"
  echo "font-size: 10pt;"
  echo "}"

  echo "--></style>"

  echo  "</head>"
  echo  "<body>"

  echo  "<table>"

  echo "<tr>"
  echo "<th colspan=\"${COLS}\">"
  echo "<h1>Sorcery Grimoires</h1>"
  echo "<h1>$(date -u)</h1>"

  if [ $grimoire ]; then
        echo  "<h1>Grimoire: " $(basename $grimoire)"</h1>"
  else
        echo  "<h1>Grimoires: " $(codex_get_all_grimoires | get_basenames)"</h1>"
  fi

  echo  "</th>"
  echo  "</tr>"

  echo  "<tr>"
  echo  "<th>Spell</th>"
  echo  "<th>Version</th>"
  echo  "<th>Updated</th>"
  echo  "<th>Website</th>"
  [[ $COLS -eq 5 ]] && echo "<th>Source</th>"
  echo  "</tr>"

  ((  COUNT=0  ))

  for  SECTION  in  `codex_get_all_sections $grimoire`;  do
    echo  "<tr>"
    echo  "<th colspan=\"${COLS}\">"
    echo  "<h2>$( basename  $SECTION )</h2>"
    echo  "</th></tr>"
    for  SPELL  in  `codex_get_spells  $SECTION`;  do
      (
        codex_set_current_spell  $SPELL

        echo  "<tr>"
        if  [  "$SPELL"  ==  "linux"  ]   ||
            [  "$SPELL"  ==  "glibc"  ];  then
            BOLD="<th>"
          UNBOLD="</th>"
        else
            BOLD="<td>"
            UNBOLD="</td>"
        fi
	if  [  -z  "$UPDATED"  ]  &&  [  "$ENTERED"  ];  then
	    UPDATED=$ENTERED
	fi
        echo  "${BOLD}${SPELL}${UNBOLD}"
        echo  "${BOLD}${VERSION}${UNBOLD}"
        echo  "<td>$UPDATED</td>"

        if  [  "$WEB_SITE"  !=  "unknown"  ];  then
	    WEBSITE="`echo  $WEB_SITE  |  cut  -c-30`..."
	    echo  "<td>"
	    echo  "<a href=\"$WEB_SITE\">$WEBSITE</a>"
	    echo  "</td>"
        else
	    echo  "<td></td>"
        fi
        if [[ $COLS -eq 5 ]]; then
            echo "<td>"
            echo "<a href=\"$SOURCE_URL\">$(echo $SOURCE | cut -c-25)</a>"
           i=2
           ii=SOURCE${i}
           while  [  -n "${!ii}"  ];  do
               iii="${ii}_URL"
               echo "<br />"
	       echo "<a href=\"${!iii}\">$(echo ${!ii} | cut -c-25)</a>"
               i=$(($i+1))
               ii=SOURCE${i}
           done
           echo "</td>"
        fi
        echo  "</tr>"
      )
      ((  COUNT++  ))
    done
  done


  echo  "<tr>"
  echo "<th colspan=\"${COLS}\">Total spells:  $COUNT</th>"
  echo "</tr>"
  echo  "</table></body></html>"
}


display()  {

  if  [  -f  "$1"  ];  then
    case  `file  -b  $1  |  cut -d ' ' -f1`  in
      ASCII)       cat  $1  |  $PAGER  ;;
      bzip2)     bzcat  $1  |  $PAGER  ;;
      gzip)   gzip -cd  $1  |  $PAGER  ;;
    esac
  else
    message  "$2"
    false
  fi

}


newer()  {

  DATE=$1
  if  [  -n  "$DATE"  ];  then
  (
    echo "Grimoire|Section|Spell|Grimoire Version|Installed Version|Added"
    echo "--------|-------|-----|----------------|-----------------|-----"
    for  SPELL_DIR  in  `codex_get_all_spells`;  do
      unset ENTERED
      .  "$SPELL_DIR/DETAILS" 1>/dev/null 2>&1
      if  [  "$ENTERED"  ]  &&  [  $ENTERED  -gt  $DATE  ];  then
        codex_set_current_spell  $SPELL_DIR
        echo "$(echo $GRIMOIRE | get_basenames)|$SECTION|$SPELL|$VERSION|${INSTALLED:="-"}|$ENTERED"
      fi
    done
  ) | column -t -s "|"
  else
    help  |  $PAGER
  fi

}


older()  {

  DATE=$1
  if  [  -n  "$DATE"  ];  then
  (
    echo "Grimoire|Section|Spell|Grimoire Version|Installed Version|Added"
    echo "--------|-------|-----|----------------|-----------------|-----"
    for  SPELL_DIR  in  `codex_get_all_spells`;  do
      unset ENTERED
      .  "$SPELL_DIR/DETAILS" 1>/dev/null 2>&1
      if  [  "$ENTERED"  ]  &&  [  $ENTERED  -lt  $DATE  ];  then
        codex_set_current_spell  $SPELL_DIR
        echo "$(echo $GRIMOIRE | get_basenames)|$SECTION|$SPELL|$VERSION|${INSTALLED:="-"}|$ENTERED"
      fi
    done
  ) | column -t -s "|"
  else
    help  |  $PAGER
  fi

}


show_from()  {

  cd  $INSTALL_LOGS
  grep  "`esc_str $1`$"  *

}


show_spell_component()  {

  local        COMPONENT=$1
  local       SPELL_NAME=$2
  local  SPELL_DIRECTORY=`codex_find_spell_by_name  $SPELL_NAME`
  if  [  -e  $SPELL_DIRECTORY/$COMPONENT  ];  then
    cat      $SPELL_DIRECTORY/$COMPONENT
  fi

}


#-----------------------------------------------------------------------
#
# gaze_search 
#
# parameter processing for the search routines.
# the case statement should be self-explanatory 
#
#-----------------------------------------------------------------------

gaze_search() {
    case $1 in

     -name) shift; real_name_search  "$@"  ;;
    -short) shift; real_short_search "$@"  ;;
         *)        real_long_search  "$@"  ;;

    esac
}


#-----------------------------------------------------------------------
#
# real_name_search pattern(s) 
#
# searches for pattern(s) in the name of all spells.
# it searches in the codex.index files for the sake of speed 
#
#-----------------------------------------------------------------------

real_name_search() {
    local grimoire pattern

    for grimoire in $(codex_get_all_grimoires); do
        for pattern in "$@"; do
            gawk ' BEGIN {
                        OFS=""
                        IGNORECASE=1
                        quiet = "'$GAZE_VERBOSE'"
                    }
                    /^[^[:blank:]]*'"$pattern"'/ {
                        if (quiet) {
                            print $1
                        }
                        else {
                            print "'"$pattern"' -> ", $1 
                        }
                    }
                ' "$grimoire/$SPELL_INDEX_FILE"
        done
    done
}


#-----------------------------------------------------------------------
#
# grep_find_grimoire path filename pattern
#
# path should be a grimoire, since it only searches files in a specific
# depth
# filename is the filename it searches for in path
# pattern is the pattern it searches for in the files
#
# returns the full path to the matching files
# eg /var/lib/sorcery/codex/grimoire/games/coal/DETAILS
#
#-----------------------------------------------------------------------

grep_find_grimoire() {
        local path=$1
        local name=$2
        local pattern="$3"

        codex_find_in_grimoire "$path" "$name" | xargs grep -il -- "${pattern}"
}


#-----------------------------------------------------------------------
#
# real_short_search pattern(s) 
#
# searches for pattern(s) in the SHORT field of every SPELL in every 
# grimoire
#
#-----------------------------------------------------------------------

real_short_search() {
    local pattern grimoire spell spellname

    for pattern in "$@"; do
        for grimoire in $(codex_get_all_grimoires); do
            for spell in $(
    grep_find_grimoire $grimoire "DETAILS" "SHORT=.*${pattern}"
                        ); do

                spellname=$(basename $(dirname $spell))
                if [[ $GAZE_VERBOSE == 0 ]]; then
                    echo $spellname
                else
                    echo "$pattern -> $spellname" 
                fi

            done
        done
    done
}



real_long_search()  {
  local atSpell=0
  local file
  local SEARCH

  if ! [[ $GAZE_VERBOSE == 0 ]] ; then
	echo  "Searching...   "
  fi

  let j=0	

  SEARCH=''
  for pattern in "$@"; do
    SEARCH="$SEARCH -e $pattern"
  done

  for file in `codex_get_all_spells | sed 's/$/\/DETAILS/' | xargs grep -il $SEARCH`; do
     for pattern in "$@"; do
       SEARCH_RESULTS[$j]=$(gawk 'BEGIN{ORS = ""; IGNORECASE=1; inLongDesc=0}
         /'"${pattern}"'/{
           if(/^[[:blank:]]*SPELL/)   {print "(Name Match)";        exit 0;}
           if(/^[[:blank:]]*SHORT/)   {print "(Short Description)"; exit 0;}
           if(inLongDesc) {print "(Description)";       exit 0;}
         }
         /cat[[:blank:]]*<<[[:blank:]]*EOF/{inLongDesc = 1;}
         /^EOF$/{inLongDesc=0;} ' $file)

      if [[ ${SEARCH_RESULTS[$j]} ]]; then
        SEARCH_RESULTS[$j]="$pattern ->  $(basename $(dirname $file) ) ${SEARCH_RESULTS[$j]}"
        if [[ $GAZE_VERBOSE == 0 ]]; then
          basename $SPELL_DIRECTORY
        else
          clear_line
          echo ${SEARCH_RESULTS[$j]}
        fi
        let j++
      fi

    done
  done

  if ! [ "$GAZE_VERBOSE" == "0" ]; then
    clear_line
  fi

unset SEARCH_RESULTS

}


service()  {
	
  for  SPELL  in  `codex_get_all_spells`;  do
    if    [  -f  $SPELL/services  ]  &&
	  grep  -q  -i  "$1"  $SPELL/services
    then  echo  "$( basename  $SPELL )"
    fi
  done
  
}


#---------------------------------------------------------------------
##=item gaze_provides <feature>
##
## Given a feature, shows a list of spells that provide the feature
## or functionality.  For example:
##
##    % gaze provides alsa-drivers
##    alsa-driver
##    linux-devel
##    linux-dj
##
## This output indicates that alsa-driver, linux-devel, and linux-dj
## all provide the alsa-drivers feature.
##
#---------------------------------------------------------------------
gaze_provides()  {

local spell

  for feature in "$@"; do
        ! [[ $GAZE_VERBOSE == 0 ]] &&
        message "${SPELL_COLOR}${feature}:${DEFAULT_COLOR}"
        spell=$(find_providers "$feature")
        if [[ "$spell" ]]; then
                echo "$spell"
        else
                echo "no providers found"
        fi
  done
}


specific_voyeur()
{
  if ! [ -d "${LOCK_DIR}/cast.$1" ]
  then
    return 1
  fi
  nice -n +20			\
   tail /tmp/$1.compile.log	\
    --follow=name --pid=`ls "${LOCK_DIR}/cast.$1"` 2>/dev/null
}


any_voyeur()
{
  local FILE=`find $LOCK_DIR -maxdepth 1 -mindepth 1 -name "cast.*" |
         sed "s/.*\/cast\.//"` # We happily assume no spell names contain "cast."
  [ $FILE ] || return 1
  debug "voyeur" "Looking at spell \"$FILE\""
    nice -n +20				\
       tail /tmp/$FILE.compile.log	\
           --follow=name --pid=`ls "${LOCK_DIR}/cast.$FILE"` 2>/dev/null
}


activate_voyeur()  {

  if  [  -n  "$1"  ]  &&
      !  find_section  $1  >  /dev/null
  then  ((  DEFAULT_DELAY  =  $1  *  60  ))
        shift  1
  fi

  for  SPELL  in  $@;  do
    specific_voyeur $SPELL
  done

  DEFAULT_DELAY=${DEFAULT_DELAY:=60}
  DELAY=$DEFAULT_DELAY
  message  "${MESSAGE_COLOR}Waiting ${DEFAULT_DELAY} seconds for a cast to begin.${DEFAULT_COLOR}"
  while ((DELAY>0));
  do
    if any_voyeur
    then
      DELAY=$DEFAULT_DELAY
      message "${MESSAGE_COLOR}Waiting ${DEFAULT_DELAY} seconds for another cast to begin.${DEFAULT_COLOR}"
      global_clean_resources # normally an internal liblock function, inserted to clean out dead casts
    else
      sleep 1
      let DELAY--
    fi
  done

}


show_orphans()  {

  for  SPELL  in  `grep -v exiled  $SPELL_STATUS  |  cut  -d :  -f1`;  do
    if    !  cut  -d :  -f2-  $DEPENDS_STATUS  |
             grep             "^`esc_str $SPELL`:"       |
             grep  -q         ":on:"
    then     echo   $SPELL
    fi
  done

}




#---------------------------------------------------------------------
##=item gaze_show_website <spell>
##
## Shows the website/home page for the given spell.
##
#---------------------------------------------------------------------
gaze_show_website()  {

  for spell in $@; do
    if  codex_set_current_spell_by_name  $spell;  then
      if  [  -n  "$WEB_SITE"  ];  then
        ! [[ $GAZE_VERBOSE == 0 ]] &&
        message "${SPELL_COLOR}${spell}:${DEFAULT_COLOR}"
        echo  $WEB_SITE
      else
        echo  "  "
        echo  "No website found for '$spell'.  If you know of a website for"
        echo  "'$spell',  please let the Source Mage developers know so that"
        echo  "it can be included in future versions of the Source Mage"
        echo  "grimoire.  You can report the omission at the Source Mage"
        echo  "bug tracking website:"
        echo  "  "
        echo  "           http://bugs.sourcemage.org/"
      fi
    else
      echo  "  "
      echo  "'$spell' is not a spell in the current grimoire(s).  If it's"
      echo  "not a typo and it's a spell you'd really like to see, consider"
      echo  "creating a spell for it yourself.  For instructions on how to"
      echo  "write & submit spells, see the Source Mage Wiki:"
      echo  "  "
      echo  "             http://wiki.sourcemage.org."
    fi
  done
}

show_maintainer()  {

  for section in $@; do
    ! [[ $GAZE_VERBOSE == 0 ]] &&
    message "${SPELL_COLOR}${section}:${DEFAULT_COLOR}"
    SECTION=`codex_find_section_by_name $section`

    if  [  -d  "$SECTION"  ];  then

      if  [  -f  "$SECTION/MAINTAINER"  ];  then
        cat $SECTION/MAINTAINER
      else
        echo "No maintainer available for section '$( basename  $SECTION )'"
      fi

    else

      echo  "No such section"

    fi
  done

}


show_history()  {

  local SPELL=`codex_find_spell_by_name  $1`

  if  [  -n  "$SPELL"  ];  then

    if  [  -f  "$SPELL/HISTORY"  ]; then
      cat  $SPELL/HISTORY
    else
      echo "No history available for spell '$( basename  $SPELL )'"
    fi

  else

    echo "No such spell '$1'"

  fi
}


#---------------------------------------------------------------------
##=item gaze_show_section [<section> [<section>...]]
##
## Given a section name, shows a table of spells in that section along
## with their grimoire version and installed verion
##
#---------------------------------------------------------------------
gaze_show_section()  {

  local SECTION_NAME

  if  [  $# -gt 0  ]; then

    (
      for  SECTION_NAME  in  $@;  do
        local SECTION=$(codex_find_section_by_name  $SECTION_NAME)
        [[ $SECTION ]] && codex_get_spell_names $SECTION
      done
    ) | column

  else

    codex_get_all_section_names | column

  fi

}


#---------------------------------------------------------------------
##=item gaze_show_section_version_table <section>
##
## Given a section name, shows a table of spells in that section along
## with their grimoire version and installed verion
##
#---------------------------------------------------------------------
gaze_show_section_version_table()  {

   local  SPELLS=`codex_get_spells $1`

   (

     echo  "Grimoire|Section|Spell|Grimoire Version|Installed Version"
     echo  "--------|-------|-----|----------------|-----------------"

     for  spell  in  $SPELLS;  do 

       codex_set_current_spell  $spell                            &&
       local  INSTALLED=`installed_version  $SPELL`               && 
       echo  "$(echo $GRIMOIRE | get_basenames)|$SECTION|$SPELL|${VERSION:="-"}|${INSTALLED:="-"}"

     done 

   ) | column -t -s "|"

}


#---------------------------------------------------------------------
##=item gaze_show_spell_version_table <spell> [<spell> ...]
##
## Shows the versions of spells, both the version in the grimoire and
## the version installed on the system.  
##
#---------------------------------------------------------------------
gaze_show_spell_version_table()  {

  (
	echo  "Grimoire|Section|Spell|Grimoire Version|Installed Version"
    echo  "--------|-------|-----|----------------|-----------------"
 
   for  SPELL  in  $@; do 

      codex_set_current_spell  $SPELL                        &&
      local  INSTALLED=`installed_version  $SPELL`           &&
	  echo  "$(echo $GRIMOIRE | get_basenames)|$SECTION|$SPELL|${VERSION:="-"}|${INSTALLED:="-"}"

    done 

  ) | column -t -s "|"

}


#---------------------------------------------------------------------
##=item gaze_show_version <spell or section> [<spell or section> ...]
##
## Shows the versions of spells, both the version in the grimoire and
## the version installed on the system.  
##
#---------------------------------------------------------------------
gaze_show_version()  {
    
  local SPELLS_AND_SECTIONS=$@
  local SPELLS=
  local UNKNOWN=

  for  spell_or_section  in  $SPELLS_AND_SECTIONS;  do

    if  codex_find_spell_or_section_by_name  $spell_or_section;  then

      [  -n  "$CODEX_FOUND_SECTION"  ]                                      &&
      gaze_show_section_version_table  $CODEX_FOUND_SECTION  2>  /dev/null  &&
      echo " "

      [  -n  "$CODEX_FOUND_SPELL"  ]    &&
      SPELLS="$SPELLS $CODEX_FOUND_SPELL"

    else
      UNKNOWN="$spell_or_section $UNKNOWN"
    fi 

  done

  [  -n  "$SPELLS"  ]  &&
  gaze_show_spell_version_table  $SPELLS  2>  /dev/null  &&
  echo " "


  [  -n  "$UNKNOWN"  ]                  &&
  message "Unknown Spells or Sections"  &&
  message "--------------------------"  &&
  message "$UNKNOWN"

}

#---------------------------------------------------------------------
##=item gaze_show_versions <spell>
##
## Shows the all versions of spell, all versions in all grimoires and 
## the version installed on the system.
##
#---------------------------------------------------------------------
gaze_show_versions()  {

  local SPELL=$1
  local SPELL_DIRECTORY=
  local GRIMOIRE=
  local GRIMOIRES=
  local ECHO_INSTALLED=1

  if ! codex_does_spell_exist $SPELL
  then return 1
  fi

  local INSTALLED=`installed_version $SPELL`

  GRIMOIRES=$(codex_get_all_grimoires)

  (

  echo "Grimoire|Section|Spell|Grimoire Version|Installed Version"
  echo "--------|-------|-----|----------------|-----------------"

  for GRIMOIRE in $GRIMOIRES
  do
    if SPELL_DIRECTORY=$(codex_cache_spell_lookup $SPELL $GRIMOIRE)
    then
      codex_set_current_spell $SPELL_DIRECTORY

	  if [ $ECHO_INSTALLED -eq 1 ]
	  then
        echo "$(echo $GRIMOIRE | get_basenames)|$SECTION|$SPELL|$VERSION|${INSTALLED:="-"}"
        ECHO_INSTALLED=0
      else
        echo  "$(echo $GRIMOIRE | get_basenames)|$SECTION|$SPELL|$VERSION|-"
      fi

    else
      echo "$(echo $GRIMOIRE | get_basenames)|-|-|-|-"
    fi
  done

  ) | column -t -s "|"

  echo
}



#---------------------------------------------------------------------
##=item gaze_show_section_license_table <section>
##
## Given a section name, shows a table of spells in that section along
## with their licenses.
##
#---------------------------------------------------------------------
gaze_show_section_license_table()  {

   local  SPELLS=`codex_get_spells $1`

   (

     echo  "Section|Spell|License(s)"
     echo  "-------|-----|----------"

     for  spell  in  $SPELLS;  do 

       codex_set_current_spell  $spell        &&
       echo  "$SECTION|$SPELL|${LICENSE[@]}"

     done 

   ) | column -t -s "|"

}


#---------------------------------------------------------------------
##=item gaze_show_spell_license_table <spell> [<spell> ...]
##
## Shows the licenses of spells
##
#---------------------------------------------------------------------
gaze_show_spell_license_table()  {

  (
    echo  "Spell|License(s)"
    echo  "-----|----------"
 
    for  SPELL  in  $@; do 

      codex_set_current_spell  $SPELL                        &&
      echo "$SPELL|${LICENSE[@]}"

    done 

  ) | column -t -s "|"

}


#---------------------------------------------------------------------
##=item gaze_show_license_table <license> [<license> ...]
##
## Shows the information about the given licenses. 
##
#---------------------------------------------------------------------
gaze_show_license_table()  {

  
  (
    echo  "Abbr|License Full Name|URL"
    echo  "----|-----------------|---"

    for  LICENSE  in  $@; do 

      grep "^$LICENSE|"  ${SM_LICENSE_LIST}  2> /dev/null

    done 

  ) | column -t -s "|"

}


#---------------------------------------------------------------------
##=item gaze_show_grimories 
##
## Shows lising of installed grmoires by grimoire name only.
##
#---------------------------------------------------------------------
gaze_show_grimoires()  {

	echo  ""
	echo  ""
	echo  "Installed Grimoires: " $(codex_get_all_grimoires | get_basenames)
	echo  ""
	echo  ""
	exit
	
}


#---------------------------------------------------------------------
##=item gaze_show_license <spell, section, or license> [<spell, section, or license> ...]
##
## Shows the licenses of spells if a spell or section name is given.
## Shows info a license if a license name is given.
##
#---------------------------------------------------------------------
gaze_show_license()  {
    
  local SPELLS_AND_SECTIONS_AND_LICENSES=$@
  local SPELLS=
  local LICENSES=
  local UNKNOWN=

  for  spell_section_or_license  in  $SPELLS_AND_SECTIONS_AND_LICENSES;  do

    if  codex_find_spell_or_section_by_name  $spell_section_or_license;  then

      [  -n  "$CODEX_FOUND_SECTION"  ]                                      &&
      gaze_show_section_license_table  $CODEX_FOUND_SECTION  2>  /dev/null  &&
      echo " "

      [  -n  "$CODEX_FOUND_SPELL"  ]    &&
      SPELLS="$SPELLS $CODEX_FOUND_SPELL"

    elif  grep -q "^`esc_str $spell_section_or_license`|"  ${SM_LICENSE_LIST} 2> /dev/null;  then
      LICENSES="$LICENSES $spell_section_or_license"
    else
      UNKNOWN="$spell_section_or_license $UNKNOWN"
    fi 

  done

  [  -n  "$SPELLS"  ]                                    &&
  gaze_show_spell_license_table  $SPELLS  2>  /dev/null  &&
  echo " "

  [  -n  "$LICENSES"  ]                              &&
  gaze_show_license_table  $LICENSES  2>  /dev/null  &&
  echo " "


  [  -n  "$UNKNOWN"  ]                              &&
  message "Unknown Spells or Sections or Licenses"  &&
  message "--------------------------------------"  &&
  message "$UNKNOWN"

}

gaze_show_installed() {

  if    [  -z  "$1"    ]
        then  $PAGER   $SPELL_STATUS
  else
        for spell in $@; do
                ! [[ $GAZE_VERBOSE == 0 ]] &&
                message  "${SPELL_COLOR}${spell}:${DEFAULT_COLOR}"
                VERSION=$(installed_version  $spell)
                if  [  -n  "$VERSION"  ]; then
                        echo   "$VERSION"
                else
                        message  "not installed"
                fi
        done
  fi
}

gaze_show_short_description() {

  for spell in $@; do
        ! [[ $GAZE_VERBOSE == 0 ]] &&
        message "${SPELL_COLOR}${spell}:${DEFAULT_COLOR}"
        (
          codex_set_current_spell_by_name  $spell           &&
          echo $SHORT
        )                                                 ||
        message  "No details found"
  done
}

gaze_show_long_description() {

  for spell in $@; do
        ! [[ $GAZE_VERBOSE == 0 ]] &&
        message "${SPELL_COLOR}${spell}:${DEFAULT_COLOR}"
        (
          codex_set_current_spell_by_name  $spell           &&
          codex_get_spell_description  $SPELL_DIRECTORY
        )                                       ||
        message  "No details found"
  done
}

gaze_show_where() {
	for spell in $@; do
		SECTION=$(codex_get_spell_section_name  $spell)
                if ! [[ $GAZE_VERBOSE == 0 ]]; then
		        if [[ $SECTION ]]; then
			        message "$spell -> $SECTION"
                        else
                                message "$spell -> no such spell"
                        fi
		else
                        [[ $SECTION ]] && message "$SECTION"
		fi
	done
}

gaze_show_depends() {
    local spell="$1"
    local MAX_DEPTH=$2 #as a global for show_depends.

    codex_does_spell_exist "$spell" && show_depends "$spell" | sort | uniq
}


gaze_show_dependencies() {
    local SPELL=$1
    [[ $# == 2 ]] && MAX_DEPTH=$2

    (
        query() {
            return 0
        }
        depends() {
                recurse $1 $DEPTH "depends"
                return 0
        }
        optional_depends() {
                recurse $1 $DEPTH "optional"
                return 0
        }
        requires() {
                recurse $1 $DEPTH "requires"
                return 0
        }
        repeat () {
            local CHAR="$1" COUNT="$2"
    
            while (( COUNT-- )); do echo -en "$CHAR"; done
        }
    
        recurse () {
            local name=$1 DEPTH=$2 WHAT=$3
    
            [[ $MAX_DEPTH ]] && [[ $DEPTH -ge $MAX_DEPTH ]] && return 1
    
            repeat "\t" $DEPTH
            echo "$name ($WHAT)"
            grep () {
               local foo=$( which grep )
               $foo "$@"
            }
    
            local SPELL=$(codex_find_spell_by_name $name)
            [[ -e "$SPELL/DEPENDS" ]] &&
            (
                    (( DEPTH++ ))
                    grep () { return 0; }
                    source "$SPELL/DEPENDS" 2>/dev/null
            )
        }
        recurse $SPELL
    )
}

gaze_show_size () {
    local spell
    for spell in "$@"; do
        local version=$(installed_version $spell)
        local file="$INSTALL_LOGS/$spell-$version"
        cat $file | xargs ls -lgd 2> /dev/null |grep '^[^dl]' | \
            awk '{ x += $5 } 
                END { print "'$spell' -> " x " bytes in " NR " files." }'
    done
}


parse()  {

  if [ $1 == "-q" ]; then
        shift;
        GAZE_VERBOSE=0
  fi


  SPELL=$2
  SECTION=$2
  VERSION=`installed_version  $SPELL`

  case  $1  in

        # Spell components. In alphabetical order.
           BUILD)  show_spell_component $1 $2            ;;
       CONFIGURE)  show_spell_component $1 $2            ;;
       CONFLICTS)  show_spell_component $1 $2            ;;
         DETAILS)  show_spell_component $1 $2            ;;
         DEPENDS)  show_spell_component $1 $2            ;;
           FINAL)  show_spell_component $1 $2            ;;
         HISTORY)  show_spell_component $1 $2            ;;
         INSTALL)  show_spell_component $1 $2            ;;
           PATCH)  show_spell_component $1 $2            ;;
      POST_BUILD)  show_spell_component $1 $2            ;;
    POST_INSTALL)  show_spell_component $1 $2            ;;
     POST_REMOVE)  show_spell_component $1 $2            ;;
       PRE_BUILD)  show_spell_component $1 $2            ;;
     PRE_INSTALL)  show_spell_component $1 $2            ;;
      PRE_REMOVE)  show_spell_component $1 $2            ;;
         PREPARE)  show_spell_component $1 $2            ;;
        PROVIDES)  show_spell_component $1 $2            ;;
        TRIGGERS)  show_spell_component $1 $2            ;;

        # Other options
            html)  shift; gaze_catalog_html $@           ;;
          export)  export_snapshot                       ;;
          import)  import_snapshot   $2                  ;;
         section)  shift; gaze_show_section $@           ;;
         version)  shift; gaze_show_version $@           ;;
		 versions)  shift; gaze_show_versions $@         ;;
         license)  shift; gaze_show_license $@           ;;
           alien)  alien                                 ;;
            from)  show_from         $2                  ;;
           newer)  newer             $2                  ;;
           older)  older             $2                  ;;
           prune)  prune                                 ;;
         sources)  sources           $SPELL              ;;
        grimoire)  shift; gaze_catalog $@  |   $PAGER    ;;
       grimoires)  gaze_show_grimoires                   ;;
          search)  shift; gaze_search "$@"               ;;
         service)  service       "$2"                    ;;
        provides)  shift; gaze_provides $@               ;;
         depends)  shift; gaze_show_depends  "$@"        ;;
    dependencies)  shift; gaze_show_dependencies  "$@"   ;;
         orphans)  show_orphans        |  sort  |  uniq  ;;
         history)  show_history  "$2"                    ;;
     website|url)  shift; gaze_show_website           $@ ;;
      maintainer)  shift; show_maintainer             $@ ;;
       installed)  shift; gaze_show_installed         $@ ;;
           short)  shift; gaze_show_short_description $@ ;;
            what)  shift; gaze_show_long_description  $@ ;;
           where)  shift; gaze_show_where             $@ ;;
            size)  shift; gaze_show_size              $@ ;;
       checkmd5s)  shift; gaze_md5check               $@ ;;


    compile)  if  [  -z  "$VERSION"  ];  then
                  codex_set_current_spell_by_name  $2
              fi
              display  $COMPILE_LOGS/$SPELL-$VERSION$EXTENSION   \
                       "Compile log for $SPELL does not exist"
              ;;

    install)  display  $INSTALL_LOGS/$SPELL-$VERSION   \
              "Install log for $SPELL does not exist"
              ;;

    sum)  [  -n  "$SPELL"  ]                         &&
          checksum  "$INSTALL_LOGS/$SPELL-$VERSION"  ||
          checksum  "$INSTALL_LOGS/*"
          ;;


    md5sum)  [  -n  "$SPELL"  ]                             &&
             md5sum_files  "$INSTALL_LOGS/$SPELL-$VERSION"  ||
             md5sum_files  "$INSTALL_LOGS/*"
             ;;

   voyeur)  shift  1;  activate_voyeur  $@  ;;

      pam)  find_pam_aware  ;;

 install-queue)  display  $INSTALL_QUEUE  "Install queue does not exist"  ;;

  remove-queue)  display  $REMOVE_QUEUE   "Remove queue does not exist"   ;;

             *)  help  ;;

  esac

}


. /etc/sorcery/config
if  [  $#  == 0  ];  then  help  |  $PAGER;  else  parse  "$@";  fi


#---------------------------------------------------------------------
##=back
##
##=head1 LICENSE
##
## This software 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 software 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 software; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
##
#---------------------------------------------------------------------
