# edit-tree-randomly:
#
################################################################
# Copyright (C) 2003 Robert Anderson and Tom Lord
#
# See the file "COPYING" for further information about
# the copyright and warranty status of this work.
#

limit_size=yes

ADD="tla add"
DEL="tla delete"
MV="tla move"

max_files=15
max_dirs=10
max_symlinks=8
num_edits_bound=100

echo '################################'
echo '#'
echo '# baseline configuration'
echo '#'
echo '################################'


file_add_chances=72
file_delete_chances=36
file_rename_chances=72

dir_add_chances=72
dir_delete_chances=24
dir_rename_chances=144

symlink_add_chances=72
symlink_delete_chances=36
symlink_rename_chances=72

file_patch_chances=72
symlink_retarget_chances=72
chmod_chances=0

move_file_to_symlink_chances=72
move_symlink_to_file_chances=72


# echo '################################'
# echo '#'
# echo '# tree-delta configuration'
# echo '#'
# echo '################################'
#
#
# file_add_chances=72
# file_delete_chances=12
# file_rename_chances=72
#
# dir_add_chances=72
# dir_delete_chances=12
# dir_rename_chances=144
#
# symlink_add_chances=72
# symlink_delete_chances=12
# symlink_rename_chances=72
#
# file_patch_chances=72
# symlink_retarget_chances=72
# chmod_chances=0
#
# move_file_to_symlink_chances=72
# move_symlink_to_file_chances=72




random_range=$((  $file_add_chances \
                + $file_delete_chances \
                + $file_rename_chances \
                \
                + $dir_add_chances \
                + $dir_delete_chances \
                + $dir_rename_chances \
                \
                + $symlink_add_chances \
                + $symlink_delete_chances \
                + $symlink_rename_chances \
                \
                + $file_patch_chances \
                + $symlink_retarget_chances \
                + $chmod_chances \
                \
                + $move_file_to_symlink_chances \
                + $move_symlink_to_file_chances ))




file_add ()
{
  echo -n "file add: "

  n_files=`count file`
  if [ ! -z $limit_size -a "(" $n_files -gt $max_files ")" ] ; then
    echo "too many files already"
    continue
  else
    newparent=`choose dir`
    newfile="$newparent/file$RANDOM"
    check_exists file $newfile

    echo $RANDOM > $newfile

    # 1 in 2 files are binary, in the GNU diff sense of the word
    #
    type=`random_upto 2`
    if [ $type -eq 1 ]; then
      echo -e "$RANDOM\000" > $newfile
      echo -n "(binary)"
    fi

    $ADD $newfile
    echo "($newfile)"
  fi
}


dir_add ()
{
  echo -n "dir add: "

  n_dirs=`count dir`

  if [ ! -z $limit_size -a "(" $n_dirs -gt $max_dirs ")" ] ; then
    echo "too many dirs already"
    continue
  else
    parent=`choose dir`
    newdir=dir$RANDOM
    check_exists dir $newdir

    mkdir $parent/$newdir
    if [ $? -ne 0 ]; then exit 0; fi # might not have permission
    $ADD $parent/$newdir
    echo "($parent/$newdir)"
  fi
}

symlink_add ()
{
  echo -n "symlink add: "

  n_symlinks=`count link`

  if [ ! -z $limit_size -a "(" $n_symlinks -gt $max_symlinks ")" ] ; then
    echo "too many symlinks already"
    continue
  else

    parent=`choose dir`
    newlink="$parent/link$RANDOM"
    check_exists link $newlink

    ntarget_objs=4
    target_type=`random_upto $ntarget_objs`
    case $target_type in
      1)
        target="target$RANDOM"
        ;;
      2)
        abort_if_none file
        target=`choose file`
        ;;
      3)
        target=`choose dir`
        ;;
      4)
        abort_if_none link
        target=`choose link`
        ;;
    esac

    ln -s $target $newlink
    $ADD $newlink
    echo "$newlink -> $target"
  fi
}

file_delete ()
{
  abort_if_none file

  echo -n "file delete: "
  delfile=`choose file`
  $DEL $delfile
  rm -f $delfile
  echo "($delfile)"
}

dir_delete ()
{
  echo -n "dir delete: "
  deldir=`choose dir`
  if [ "$deldir" == "." ]; then
    echo "(skipping - can't delete .)"
    continue
  fi
  rm -rf $deldir

  echo "($deldir)"
}

symlink_delete ()
{
  abort_if_none link

  echo -n "delete symlink: "
  dellink=`choose link`
  echo -n "($dellink)"
  $DEL $dellink
  rm -f $dellink
  echo
}

file_patch ()
{
  abort_if_none file

  echo -n "file patch: "
  filename=`choose file`
  set +e
  echo "$RANDOM" > $filename
  set -e
  echo "($filename)"
}

file_rename ()
{
  abort_if_none file

  echo -n "file rename: "
  oldname=`choose file`
  newparent=`choose dir`
  newname="$newparent/file$RANDOM"
  check_exists file $newname

  $MV $oldname $newname
  mv $oldname $newname
  echo "($oldname -> $newname)"
}

move_file_to_symlink ()
{
  abort_if_none file

  echo -n "move file to symlink: "

  delfile=`choose file`
  rm -f $delfile

  # add symlink
  parent=`choose dir`
  newlink="$parent/link$RANDOM"
  target="target$RANDOM"
  ln -s $target $newlink

  $MV $delfile $newlink

  echo "($delfile -> $newlink)"
}

move_symlink_to_file ()
{
  abort_if_none link

  echo -n "move symlink to file: "

  newparent=`choose dir`
  newfile="$newparent/file$RANDOM"
  check_exists file $newfile

  dellink=`choose link`
  rm -f $dellink

  echo $RANDOM > $newfile

  # 1 in 2 files are binary
  type=`random_upto 2`
  if [ $type -eq 1 ]; then
    echo -e "$RANDOM\000" > $newfile
    echo -n "(binary)"
  fi

  $MV $dellink $newfile

  echo "($delfile -> $newlink)"
}

symlink_rename ()
{
  abort_if_none link

  echo -n "link rename: "
  oldname=`choose link`
  newparent=`choose dir`
  newname="$newparent/link$RANDOM"
  check_exists link $newname

  mv $oldname $newname
  $MV $oldname $newname
  echo "($oldname -> $newname)"
}

dir_rename ()
{
  # Can't move .
  oldname=`choose dir`
  if [ "$oldname" == "." ]; then continue; fi

  echo -n "dir rename: "

  newparent=`choose dir`
  newname="$newparent/dir$RANDOM"
  check_exists dir $newname

  # This can fail if the new dir is a subdir of itself
  set +e
  mv $oldname $newname 2> /dev/null
  if [ $? -ne 0 ]; then
    echo "(randomly generated dir rename is illegal ... skipping)"
    continue;
  fi
  set -e

  echo "($oldname -> $newname)"
}

symlink_retarget ()
{
  abort_if_none link

  echo -n "link retarget: "
  oldlink=`choose link`
  target="target$RANDOM"
  rm -f "$oldlink"
  ln -s $target $oldlink
  echo "($oldlink -> $target)"
}

# count a particular type of file
#
count ()
{
  obj=$1
  case $obj in

    file)
      findtype=f
      ;;
    link)
      findtype=l
      ;;
    dir)
      findtype=d
      ;;
  esac

  rm -rf ,,list
  find . \
    -name "{arch}" -prune -o \
    -name ".arch-ids" -prune -o \
    -name ",,*" -prune -o \
    -name "++*" -prune -o \
    -type $findtype -print >> ,,list

  n=`wc -l ,,list | awk '{print $1}'`

  echo -n "$n"
}


# Get a random item from the file, dir, or link lists
#
choose ()
{
  obj=$1
  case $obj in

    file)
      findtype=f
      ;;
    link)
      findtype=l
      ;;
    dir)
      findtype=d
      ;;
  esac

  rm -rf ,,list
  find . \
    -name "{arch}" -prune -o \
    -name ".arch-ids" -prune -o \
    -name ",,*" -prune -o \
    -name "++*" -prune -o \
    -type $findtype -print >> ,,list

  n=`wc -l ,,list | awk '{print $1}'`

  num=`random_upto $n`

  name=`head -n $num ,,list | tail -n 1`

  echo -n "$name"
}

abort_if_none ()
{
  obj=$1
  case $obj in

    file)
      findtype=f
      ;;
    link)
      findtype=l
      ;;
    dir)
      findtype=d
      ;;
  esac

  rm -rf ,,list
  find . \
    -name "{arch}" -prune -o \
    -name ".arch-ids" -prune -o \
    -name ",,*" -prune -o \
    -name "++*" -prune -o \
    -type $findtype -print >> ,,list

  num=`wc -l ,,list | awk '{print $1}'`
  if [ $num -eq 0 ]; then continue; fi
}

check_exists ()
{
  obj=$1
  name=$2
  case $obj in

    file)
      findtype=f
      ;;
    link)
      findtype=l
      ;;
    dir)
      findtype=d
      ;;
  esac

  found=`find . -type $findtype -name $name -print`
  if [ ! -z "$found" ]; then
    echo "(skipping: $name already exists)"
    continue
  fi
}

random_upto ()
{
  range=$1
  num=$(( $RANDOM % $range + 1 ))
  echo -n "$num"
}

edit_tree_randomly ()
{

  edit_num=1
  num_edits=`random_upto $num_edits_bound`

  while [ $edit_num -lt $num_edits ]; do

    edit_kind=`random_upto $random_range`

    if [ $edit_kind -le $file_add_chances ] ; then
      file_add
      edit_num=$(( $edit_num + 1))
      continue
    else
      edit_kind=$(( $edit_kind - $file_add_chances ))
    fi

    if [ $edit_kind -le $file_delete_chances ] ; then
      file_delete
      edit_num=$(( $edit_num + 1))
      continue
    else
      edit_kind=$(( $edit_kind - $file_delete_chances ))
    fi

    if [ $edit_kind -le $file_rename_chances ] ; then
      file_rename
      edit_num=$(( $edit_num + 1))
      continue
    else
      edit_kind=$(( $edit_kind - $file_rename_chances ))
    fi


    if [ $edit_kind -le $dir_add_chances ] ; then
      dir_add
      edit_num=$(( $edit_num + 1))
      continue
    else
      edit_kind=$(( $edit_kind - $dir_add_chances ))
    fi

    if [ $edit_kind -le $dir_delete_chances ] ; then
      dir_delete
      edit_num=$(( $edit_num + 1))
      continue
    else
      edit_kind=$(( $edit_kind - $dir_delete_chances ))
    fi

    if [ $edit_kind -le $dir_rename_chances ] ; then
      dir_rename
      edit_num=$(( $edit_num + 1))
      continue
    else
      edit_kind=$(( $edit_kind - $dir_rename_chances ))
    fi



    if [ $edit_kind -le $symlink_add_chances ] ; then
      symlink_add
      edit_num=$(( $edit_num + 1))
      continue
    else
      edit_kind=$(( $edit_kind - $symlink_add_chances ))
    fi

    if [ $edit_kind -le $symlink_delete_chances ] ; then
      symlink_delete
      edit_num=$(( $edit_num + 1))
      continue
    else
      edit_kind=$(( $edit_kind - $symlink_delete_chances ))
    fi

    if [ $edit_kind -le $symlink_rename_chances ] ; then
      symlink_rename
      edit_num=$(( $edit_num + 1))
      continue
    else
      edit_kind=$(( $edit_kind - $symlink_rename_chances ))
    fi


    if [ $edit_kind -le $file_patch_chances ] ; then
      file_patch
      edit_num=$(( $edit_num + 1))
      continue
    else
      edit_kind=$(( $edit_kind - $file_patch_chances ))
    fi

    if [ $edit_kind -le $symlink_retarget_chances ] ; then
      symlink_retarget
      edit_num=$(( $edit_num + 1))
      continue
    else
      edit_kind=$(( $edit_kind - $symlink_retarget_chances ))
    fi

    if [ $edit_kind -le $chmod_chances ] ; then
      chmod
      edit_num=$(( $edit_num + 1))
      continue
    else
      edit_kind=$(( $edit_kind - $chmod_chances ))
    fi


    if [ $edit_kind -le $move_file_to_symlink_chances ] ; then
      move_file_to_symlink
      edit_num=$(( $edit_num + 1))
      continue
    else
      edit_kind=$(( $edit_kind - $move_file_to_symlink_chances ))
    fi

    if [ $edit_kind -le $move_symlink_to_file_chances ] ; then
      move_symlink_to_file
      edit_num=$(( $edit_num + 1))
      continue
    else
      edit_kind=$(( $edit_kind - $move_symlink_to_file_chances ))
    fi

  done
  echo "done editing."
}

###  Local Variables:
###  mode: shell-script
###  End:

# tag: Robert Anderson Sun May 18 18:13:27 PDT 2003 (edit-tree-randomly)

