#!/bin/bash
#(c) Copyright Barry Kauler 2015
#1download, 2createpackages, call support/findpkgs to create status/findpkgs_FINAL_PKGS-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION}
#i want to read this and determine a build-order for the packages in variable PKGS_SPECS_TABLE
# in file DISTRO_PKGS_SPECS-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION},
# so packages are installed into sandbox3/rootfs-complete and devx by script 3builddistro in correct order
# (and not in the order as listed in the table, as has been done up to now).
#150713 first version.
#150714 called from support/findpkgs. status/findpkgs_GENERIC_NAMES-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION} read by 3builddistro.
#150714 ignore pet pkgs.
#150715 create file PKGS_SPECS_TABLE_EXTRA, with missing pkgs.
#150716 temp files in /tmp/woof-build-order. create file PKGS_SPECS_TABLE_MERGED.
#150717 check template names when merge. remove old sorted generic names file.
#150729 improved dependency-order sort. 150730

[ ! -f DISTRO_SPECS ] && exit 1
. ./DISTRO_SPECS
[ ! -f status/findpkgs_FINAL_PKGS-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION} ] && exit 1
[ ! -f ./DISTRO_PKGS_SPECS-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION} ] && exit 1
. ./DISTRO_PKGS_SPECS-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION}

#150715
. ./PKGS_MANAGEMENT #has PKG_NAME_ALIASES, PKG_NAME_IGNORE
. ./DISTRO_COMPAT_REPOS-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION} #ex: DISTRO_COMPAT_REPOS-ubuntu-wily
#150716
[ -d /tmp/woof-build-order ] && rm -rf /tmp/woof-build-order
mkdir /tmp/woof-build-order

#line ex:
#:a52dec:|compat|Packages-pet-wary5-official|a52dec-0.7.4-w5|a52dec|0.7.4-w5||BuildingBlock|68K||a52dec-0.7.4-w5.pet||A free ATSC A52 stream decoder|puppy|wary5||

#150717 remove this file, as it gets optionally created by build-order, 3builddistro reads it if exists...
rm -f status/findpkgs_GENERIC_NAMES-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION} 2>/dev/null

#150714 handle aliases... 150716 \+ escape also required...
aliasesPTNS="$(echo "$PKG_NAME_ALIASES" | tr ' ' '\n' | grep -v '^$' | sed -e 's%,%|%g' -e 's%\*%.*%g' -e 's%\-%\\-%g' -e 's%\+%\\+%g')"
#ex: PKG_NAME_ALIASES has an entry cxxlibs,glibc*,libc-* the above creates cxxlibs|glibc.*|libc\-.*
echo "$aliasesPTNS" > /tmp/woof-build-order/aliasesPTNS

ls -1 packages-templates > /tmp/woof-build-order/template-names #150717

#150729 try better sort...
grep -v -E '^:zz|^:z_' status/findpkgs_FINAL_PKGS-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION} > /tmp/woof-build-order/todo-db1
grep -E '^:zz|^:z_' status/findpkgs_FINAL_PKGS-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION} > /tmp/woof-build-order/zz-db #want to leave these at end.
REPCNT=1
echo -n '' > /tmp/woof-build-order/sorted-db1
while [ 1 ];do
 DB1="$(tac /tmp/woof-build-order/todo-db1)" #might improve speed if reverse, tac
 echo -n '' > /tmp/woof-build-order/todo-db1
 echo -e "\n***${REPCNT}***"
 LINECNT=1
 echo "$DB1" |
 while read ALINE
 do
  echo -n '.'
  PTNname='+'"$(echo -n "$ALINE" | cut -f 5 -d '|')"'[|,&]' #this is attempt to get around circular deps.
  #depPTNs="$(echo -n "$ALINE" | cut -f 12 -d '|' | tr ',' '\n' | sed -e 's%^+%%' | cut -f 1 -d '&' | sed -e 's%^$%XXXXXXXXX%' -e 's%^%[|/]%' -e 's%$%[|0-9\\-]%')"
  depPTNs="$(echo -n "$ALINE" | cut -f 12 -d '|' | tr ',' '\n' | sed -e 's%^+%%' | cut -f 1 -d '&' | sed -e 's%^$%XXXXXXXXX%' -e 's%^%|%' -e 's%$%|%')"
  echo "$depPTNs" > /tmp/woof-build-order/dep-ptns
  FNDLINE1="$(echo "$DB1" | grep -n -f /tmp/woof-build-order/dep-ptns | grep -v "$PTNname")"
  if [ ! "$FNDLINE1" ];then
   echo "$ALINE" >> /tmp/woof-build-order/sorted-db1
#  elif [ $FNDLINE1 -le $LINECNT ];then
#   echo "$ALINE" >> /tmp/woof-build-order/sorted-db1
  else
   echo "$ALINE" >> /tmp/woof-build-order/todo-db1
  fi
  LINECNT=`expr $LINECNT + 1`
 done
 sync
 REPCNT=`expr $REPCNT + 1`
 [ $REPCNT -gt 22 ] && break
 [ ! -s /tmp/woof-build-order/todo-db1 ] && break
done
mv -f /tmp/woof-build-order/sorted-db1 status/findpkgs_FINAL_PKGS-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION}
[ -s /tmp/woof-build-order/todo-db1 ] && cat /tmp/woof-build-order/todo-db1 >> status/findpkgs_FINAL_PKGS-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION}
[ -s /tmp/woof-build-order/zz-db ] && cat /tmp/woof-build-order/zz-db >> status/findpkgs_FINAL_PKGS-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION}
echo

#150729 um, no, want to read from top of file... 150730 go back to reverse order...
#want to create a list of generic names, correct install-order, to use in 3builddistro...
echo -n '' > /tmp/woof-build-order/reverse-order
GENLIST="$(tac status/findpkgs_FINAL_PKGS-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION} | cut -f 1 -d '|' | tr '\n' ':' | tr -s ':' | tr ':' ' ')"
#GENLIST="$(cat status/findpkgs_FINAL_PKGS-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION} | cut -f 1 -d '|' | tr '\n' ':' | tr -s ':' | tr ':' ' ')"
for AGEN in $GENLIST
do
 [ "$(grep -x "$AGEN" /tmp/woof-build-order/reverse-order)" != "" ] && continue #multiple generic-names, want first only.
 echo "$AGEN" >> /tmp/woof-build-order/reverse-order
done
tac /tmp/woof-build-order/reverse-order > status/findpkgs_GENERIC_NAMES-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION}
#cat /tmp/woof-build-order/reverse-order > status/findpkgs_GENERIC_NAMES-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION}
sync
echo
echo "Have created: status/findpkgs_GENERIC_NAMES-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION}"
echo "Which is a list of generic names in correct build-order for 3builddistro."

CURDATE="$(date +%Y%m%d-%H)"
if [ -s ERROR-build-order-missing-deps ];then #150715
 echo
 echo "File 'ERROR-build-order-missing-deps' has a list of missing dependencies!"
 echo "Would you like to have these missing packages added to the package-list?"
 echo -n "ENTER only for no: "
 read yesdoit
 if [ "$yesdoit" != "" ];then
  echo -n '' > /tmp/woof-build-order/extra-pkgs
  COMPAT_DB_FILES="$(echo "$PKG_DOCS_DISTRO_COMPAT" | tr ' ' '\n' | cut -f 3 -d '|' | tr '\n' ' ')"
  ALLMISSING="$(cut -f 3 -d ' ' ERROR-build-order-missing-deps | sort -u)"
  IGNOREPKGS="$(echo "$PKG_NAME_IGNORE" | tr ' ' '\n')" #PKG_NAME_IGNORE is in file PKGS_MANAGEMENT.
  echo "$IGNOREPKGS" > /tmp/woof-build-order/ignorepkgs
  CUTMISSING="$(echo "$ALLMISSING" | grep -x -i -v -f /tmp/woof-build-order/ignorepkgs | tr '\n' ' ')"
  echo "$CUTMISSING" > /tmp/woof-build-order/cutmissing #TEST
  cut -f 5 -d '|' status/findpkgs_FINAL_PKGS-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION} > /tmp/woof-build-order/names-already
  for AMISSING in $CUTMISSING
  do
   PTNname="|${AMISSING}|"
   DBENTRY="$(grep "$PTNname" $COMPAT_DB_FILES)"
   #DB entry format: pkgname|nameonly|version|pkgrelease|category[;subcategory]|size|path|fullfilename|dependencies|description|compileddistro|compiledrelease|repo|
   DBnameonly="$(echo -n "$DBENTRY" | cut -f 2 -d '|')"
   [ "$(echo -n "$DBnameonly" | grep '\-dev$')" != "" ] && continue #ignore, coz find -dev pkgs below.
   case $DISTRO_BINARY_COMPAT in
    debian|ubuntu|devuan|raspbian) DBgenname="$(echo -n "$DBENTRY" | cut -f 7 -d '|' | rev | cut -f 1 -d '/' | rev)" ;;
    *) DBgenname="" ;;
   esac
   
   #try more thorough method to locate -dev pkgs, but only good for debian debs...
   DBnameonlydev=''
   if [ "$DBgenname" ];then
    PTNgen1="/${DBgenname}|"
    ALLpkgsnameonly="$(grep "$PTNgen1" $COMPAT_DB_FILES | cut -f 2 -d '|')"
    DEVpkgsnameonly="$(echo "$ALLpkgsnameonly" | grep '\-dev$')"
    #screen out -dev pkgs already in pkg-list...
    xDEVpkgsnameonly="$(echo "$DEVpkgsnameonly" | grep -x -v -f /tmp/woof-build-order/names-already)"
    DEVpkgsnameonly="$xDEVpkgsnameonly"
    DBnameonlydev="$(echo -n "$DEVpkgsnameonly" | tr '\n' ',' | sed -e 's%,$%%')"
   fi
   
   [ ! "$DBgenname" ] && DBgenname="$DBnameonly"
   echo -n "${DBgenname} "
   if [ "$DBnameonlydev" ];then
    if [ "$(grep "$DBnameonlydev" /tmp/woof-build-order/extra-pkgs)" == "" ];then
     if [ "$(grep "^${DBgenname}:" /tmp/woof-build-order/extra-pkgs)" != "" ];then
      PTNinsert="s%^${DBgenname}:%${DBgenname}:${DBnameonly},${DBnameonlydev},%"
      sed -i -e "$PTNinsert" /tmp/woof-build-order/extra-pkgs
     else
      echo "${DBgenname}:${DBnameonly},${DBnameonlydev}" >> /tmp/woof-build-order/extra-pkgs
     fi
    fi
   else
    if [ "$(grep "^${DBgenname}:" /tmp/woof-build-order/extra-pkgs)" != "" ];then
     PTNinsert="s%^${DBgenname}:%${DBgenname}:${DBnameonly},%"
     sed -i -e "$PTNinsert" /tmp/woof-build-order/extra-pkgs
    else
     echo "${DBgenname}:${DBnameonly}" >> /tmp/woof-build-order/extra-pkgs
    fi
   fi
  done
  #if [ -s /tmp/woof-build-order/extra-pkgs ];then
   NEWENTRIES="$(cat /tmp/woof-build-order/extra-pkgs | sed -e 's%:%|%' -e 's%^%yes|%' -e "s%$%|exe,dev,doc,nls| #ADDED ${CURDATE}%")"
   echo "$NEWENTRIES" >> /tmp/woof-build-order/extra-pkg-list
  #fi
  cp -f /tmp/woof-build-order/extra-pkg-list PKGS_SPECS_TABLE_EXTRA
  echo
  echo
  echo "Done. File PKGS_SPECS_TABLE_EXTRA has the missing packages."
  echo "You can add these into variable PKGS_SPECS_TABLE in file"
  echo "DISTRO_PKGS_SPECS-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION}."
  echo
  echo "Would you like to merge PKGS_SPECS_TABLE_EXTRA into PKGS_SPECS_TABLE?"
  echo "If you choose no, but still want to consider manually modifying the"
  echo "package-list, suggest that you type CTRL-C at the terminal"
  echo "(and close '1download control panel'), manually update"
  echo "variable PKGS_SPECS_TABLE, then run script 1download again."
  echo -n "ENTER only to merge: "
  read yesmerge
  if [ "$yesmerge" == "" ];then
   EXTRA_LIST="$(cat PKGS_SPECS_TABLE_EXTRA)"
   COMBINED_LIST="${EXTRA_LIST}
${PKGS_SPECS_TABLE}"
   COMBINED_SORTED="$(echo "$COMBINED_LIST" | sort --key=2,2 --field-separator='|')"
   echo "$COMBINED_SORTED" > /tmp/woof-build-order/combined-sorted #TEST
   #lines with same generic-name will need to be merged...
   GENERICNAME1=''; GENERICNAME2=''; ALINE1=''
   echo -n '' > PKGS_SPECS_TABLE_MERGED
   #echo "$COMBINED_SORTED" |
   while read -u 3 ALINE  #bash: need -u 3 as a nested read. ref: http://stackoverflow.com/questions/11704353/bash-nested-interactive-read-within-a-loop-thats-also-using-read
   do
    [ "$ALINE" == "" ] && continue
    LINE2FIELD1="$(echo -n "$ALINE" | cut -f 1 -d '|')" #ex: yes
    [ "$LINE2FIELD1" != "yes" ] && continue
    GENERICNAME2="$(echo -n "$ALINE" | cut -f 2 -d '|')" #ex; abiword
    MATCHflag=0
    if [ "$GENERICNAME1" == "$GENERICNAME2" ];then
     MATCHflag=1
    else
     for aPTN in `cat /tmp/woof-build-order/aliasesPTNS | tr '\n' ' '`
     do
      if [ "$(echo -n "$GENERICNAME2" | grep -i -x -E "$aPTN")" != "" ];then
       if [ "$(echo -n "$GENERICNAME1" | grep -i -x -E "$aPTN")" != "" ];then
        MATCHflag=1
        break
       fi
      fi
     done
    fi
    if [ $MATCHflag -eq 1 ];then
     #one of these is our new entry...
     OLDmkr="$ALINE"
     [ "$(echo -n "$ALINE1" | grep "ADDED ${CURDATE}")" == "" ] && OLDmkr="$ALINE1"
     #[ "$(echo -n "$ALINE" | grep "ADDED ${CURDATE}")" != "" ] && OLDmkr="$ALINE"
     #we want to merge these, however a problem if one is a pet...
     PETflag=0
     [ "$(echo -n "$ALINE1" | grep '|pet:')" != "" ] && PETflag=1
     [ "$(echo -n "$ALINE" | grep '|pet:')" != "" ] && PETflag=1
     [ "$(echo -n "$ALINE1" | cut -f 3 -d '|')" == "" ]  && PETflag=1
     [ "$(echo -n "$ALINE" | cut -f 3 -d '|')" == "" ]  && PETflag=1
     if [ $PETflag -eq 1 ];then
      echo
      echo "Would like to merge these, but one is a PET pkg:"
      echo "  ${ALINE1}"
      echo "  ${ALINE}"
      echo -n "Press '1' to dump first, '2' dump 2nd, '3' keep both (not merged): "
      read goforit
      case "$goforit" in
       "1")
        echo "  ...ok, changing first to 'no'"
        CUTOUTLASTLINE="$(head -n -1 PKGS_SPECS_TABLE_MERGED)"
        echo "$CUTOUTLASTLINE" > PKGS_SPECS_TABLE_MERGED #remove last line.
        echo -n "no|" >> PKGS_SPECS_TABLE_MERGED
        OTHERS="$(echo -n "$ALINE1" | cut -f 2- -d '|')"
        echo "$OTHERS" >> PKGS_SPECS_TABLE_MERGED
        echo "$ALINE" >> PKGS_SPECS_TABLE_MERGED
       ;;
       "2")
        echo "  ...ok, changing second to 'no'"
        echo -n "no|" >> PKGS_SPECS_TABLE_MERGED
        OTHERS="$(echo -n "$ALINE" | cut -f 2- -d '|')"
        echo "$OTHERS" >> PKGS_SPECS_TABLE_MERGED
       ;;
       *)
        echo "  ...ok, keeping both"
        L1F2="$(echo -n "$ALINE1" | cut -f 2 -d '|')"
        L2F2="$(echo -n "$ALINE" | cut -f 2 -d '|')"
        L2F3plus="$(echo -n "$ALINE" | cut -f 3- -d '|')"
        Xmkr=''
        [ "$L2F2" == "$L1F2" ] && Xmkr='x' #rename
        echo "yes|${L2F2}${Xmkr}|${L2F3plus}" >> PKGS_SPECS_TABLE_MERGED
       ;;
      esac
     else
      #merge...
      LINE2FIELD3="$(echo -n "$ALINE" | cut -f 3 -d '|')" #ex: libabiword,abiword-common,libabiword-dev
      #in case the old entry has redirection, ex exe>dir, want to keep...
      FIELD4plus="$(echo -n "$OLDmkr" | cut -f 4- -d '|')" #ex: exe,dev,doc,nls|compat:wily| #comment
      #150717 fix amending comment...
      xFIELD4plus="$(echo -n "$FIELD4plus" | sed -e 's% #.*$%%' -e 's% $%%g' -e 's%|$%%' -e "s%$%| #MERGED ${CURDATE}%")"
      LINE1FIELD3="$(echo -n "$ALINE1" | cut -f 3 -d '|')"
      [ "$LINE1FIELD3" ] && [ "$LINE2FIELD3" ] && LINE1FIELD3=",${LINE1FIELD3}"
      FIELD3combined="${LINE2FIELD3}${LINE1FIELD3}"
      xFIELD3combined="$(echo -n "$FIELD3combined" | tr ',' '\n' | sort -u | tr '\n' ',' | sed -e 's%,$%%')"
      CUTOUTLASTLINE="$(head -n -1 PKGS_SPECS_TABLE_MERGED)"
      echo "$CUTOUTLASTLINE" > PKGS_SPECS_TABLE_MERGED #remove last line.
      #150717 if a name exists in packages-templates, use that...
      xGENERICNAME="$GENERICNAME2"
      [ "$(echo -n "$GENERICNAME1" | grep -x -f /tmp/woof-build-order/template-names)" != "" ] && xGENERICNAME="$GENERICNAME1"
      echo "yes|${xGENERICNAME}|${xFIELD3combined}|${xFIELD4plus}" >> PKGS_SPECS_TABLE_MERGED
     fi
    else
     echo "$ALINE" >> PKGS_SPECS_TABLE_MERGED
    fi
    GENERICNAME1="$GENERICNAME2"
    ALINE1="$ALINE"
   done 3<<_END2
$(echo "$COMBINED_SORTED")
_END2
   #...note, using file-descriptor 3, as have nested read.
   sync
   echo
   echo "Done. A new file 'PKGS_SPECS_TABLE_MERGED' has been created."
   echo "If you want to use it, replace the contents of PKGS_SPECS_TABLE"
   echo "in file DISTRO_PKGS_SPECS-${DISTRO_BINARY_COMPAT}-${DISTRO_COMPAT_VERSION}."
   echo "Then, rerun 1download."
   echo "RIGHT NOW: Recommend type CTRL-C in terminal, to abort script, and close"
   echo "'1download control panel' window if it is on-screen."
  fi
 fi
fi
echo
echo -n "Press ENTER to continue: "
read goyes

###END###
