# 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 ))

random_name ()
{
    echo "${RANDOM}${RANDOM}x" | sed -e 's/01/\*/g' -e 's/02/\?/g'\
    	-e 's/03/\+/g' -e 's/04/\[/g' -e 's/05/\]/g' -e "s/06/\"/g"\
    	-e 's/07/	/g' -e 's/08/\\/g' -e 's/0/ /g'
}

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_name)"
    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_name)"
    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_name)"
    check_exists link "$newlink"

    ntarget_objs=4
    target_type=$(random_upto $ntarget_objs)
    case $target_type in
      1)
        target="target$(random_name)"
        ;;
      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_name)"
  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_name)"
  target="target$(random_name)"
  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_name)"
  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_name)"
  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_name)"
  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_name)"
  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 | sed -n '$p')"

  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=-h
      ;;
    dir)
      findtype=-d
      ;;
  esac

  if [ $findtype "$name" ]; 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, Christian Thaeter Sat Feb  7 08:50:42 CET 2004 (edit-tree-randomly-with-spaces)

