#!/bin/bash

# This really is a bash script, please don't change to #!/bin/sh

# TODO: rewrite, this is fugly. Maybe use perl instead of bash.

SBOROOT=${SBOROOT:-/home/urchlay/sbogit}
if [ ! -d $SBOROOT ]; then
   SBOROOT=.
fi

SELF="$( echo "$0" | sed 's,.*/,,' )"

usage() {
   cat <<EOF
$SELF: print dependency tree of SBo builds
B. Watson, 20140911. Licensed under WTFPL: Do WTF you want with this.

Usage: $SELF [-i] [-q] package [package ...]

-i   Ignore installed packages (treat everything as not installed).
-q   Output a sbopkg queue file (sqf). With -i, this will be a complete
     queue, with all deps listed. Without -i, the queue file won't contain
     packages that are already installed (which might mean no output at
     all).

A local copy of the slackbuilds.org repository is required, created
with e.g. rsync. By default, this script assumes the current directory
is a mirror of the Slackware version you're running, but you can set
SBOROOT in the environment to use a different location. Example:

export SBOROOT=/home/bob/sbomirror/14.1

The SBOROOT (or current dir) needs to contain the category directories
(academic, accessibility, audio, etc etc).
EOF
}

print_installed_status() {
   if [ "$IGNORE" = "yes" ]; then
      echo
      return
   fi
   pkg_is_installed $1 >/dev/null && echo " (installed)" || echo " (NOT installed)"
}

find_deps() {
   local i
   local req
   local REQUIRES
   local info=$(/bin/ls $SBOROOT/*/$2/$2.info 2>/dev/null | head -1)

	if [ -z "$info" ]; then
		echo "$SELF: $2: no such package" 1>&2
		RETVAL=1
		return;
	fi

   eval $(grep ^REQUIRES= $info)
   if [ "$REQUIRES" = "" ]; then
      return
   fi
   for req in $REQUIRES; do
      for i in $(seq 1 $1 ); do
         echo -n "   "
      done
      echo -n $req
      if [ "$req" = "%README%" ]; then
         echo
      else
         print_installed_status $req
         if [ "$QUEUE" = "yes" ]; then
            if [ "$IGNORE" = "yes"  ] || ! pkg_is_installed $req ; then
               echo $1 $req >> $QTMPFILE
            fi
         fi
         find_deps $(( $1 + 1 )) $req
      fi
   done
}

while [ "$argsdone" != "yes" ]; do
   case "$1" in
      ''|-h|-help|--help) usage; exit 0 ;;
		-iq|-qi) QUEUE=yes ; IGNORE=yes ; shift ;;
      -q) QUEUE=yes ; shift ;;
      -i) IGNORE=yes ; shift ;;
      -*) echo "Unknown option $1"; usage; exit 1 ;;
      *) argsdone=yes ;;
   esac
done

if [ "$QUEUE" = "yes" ]; then
   QTMPFILE=${TMP:-/tmp}/sbodeps.$$.$RANDOM
   rm -f $QTMPFILE

   # save old stdout to fd 3, suppress stdout since we don't print our tree
   exec 3>&1 1>/dev/null
fi

if [ ! -e "$SBOROOT/system" ]; then
	echo "$SELF: path \"$SBOROOT\" doesn't look like an SBo repo, set SBOROOT in environment" 1>&2
	exit 1
fi

RETVAL=0

for arg; do
   echo -n $arg
   print_installed_status $arg
   if [ "$QUEUE" = "yes" ]; then
  		if ! pkg_is_installed $arg || [ "$IGNORE" = "yes" ]; then
			echo 0 $arg >> $QTMPFILE
		fi
	fi
   find_deps 1 $arg
done

# The queue temp file contains the same info as the regular
# tree, though less human-readable (depth numbers instead of indents).

# To turn it into a .sqf, sort it depth-first, and remove any duplicates
# (can't use sort -u or uniq, as dups might occur at different depths &
# thus not be on consecutive lines).

if [ "$QUEUE" = "yes" -a -e "$QTMPFILE" ]; then
   exec 1>&3 # restore old stdout
   for q in $(sort -nr $QTMPFILE | cut -d' ' -f2); do
      r=seen_$(echo $q | sed 's,[^A-Za-z0-9_],_,g')
      s=${!r} # bash indirect variable ref, yay
      if [ "$s" != "yes" ]; then
         echo $q
         eval $r="yes"
      fi
   done
   rm -f $QTMPFILE
fi

exit $RETVAL