#!/bin/bash
cvmfs_test_name="Rename of Directory containing Changes"
cvmfs_test_autofs_on_startup=false
cvmfs_test_suites="quick"

produce_initial_files_in() {
  local working_dir=$1

  pushdir $working_dir

  mkdir contains_nothing

  mkdir contains_file
  echo "another useless file" > contains_file/file

  mkdir contains_empty_dir
  mkdir contains_empty_dir/empty_dir

  mkdir contains_dir
  mkdir contains_dir/dir
  echo "useless file content" > contains_dir/dir/useless

  mkdir contains_many_entries
  mkdir contains_many_entries/dir
  echo "nothing to see here" > contains_many_entries/file

  popdir
}

add_file_and_rename_parent() {
  local working_dir=$1

  pushdir $working_dir

  echo "additional file for testing" > contains_nothing/useful
  mv contains_nothing contains_nothing_renamed

  popdir
}

remove_file_and_rename_parent() {
  local working_dir=$1

  pushdir $working_dir

  rm -f contains_file/file
  mv contains_file contains_file_renamed

  popdir
}

remove_empty_directory_and_rename_parent() {
  local working_dir=$1

  pushdir $working_dir

  rm -fR contains_empty_dir/empty_dir
  mv contains_empty_dir contains_empty_dir_renamed

  popdir
}

remove_directory_and_rename_parent() {
  local working_dir=$1

  pushdir $working_dir

  rm -fR contains_dir/dir
  mv contains_dir contains_dir_renamed

  popdir
}

remove_directory_among_many_entries_and_rename_parent() {
  local working_dir=$1

  pushdir $working_dir

  rm -fR contains_many_entries/dir
  mv contains_many_entries contains_many_entries_renamed

  # On RHEL 5 this is disallowed by SELinux for some reason. I am not sure, but
  # I suppose that is a bug of either AUFS or SELinux due to some funny labeling
  #
  # respective SELinux audit.log entry:
  # type=AVC msg=audit(...:59864): avc:  denied  { associate } for
  # pid=... comm="mv" name="contains_many_entries_renamed"
  # scontext=system_u:object_r:unlabeled_t:s0 tcontext=system_u:object_r:fs_t:s0
  # tclass=filesystem
  #
  # Instead of adding an allow-rule to the cvmfs SELinux module, I introduced
  # this little workaround that forces SELinux to keep its voice down.
  if [ $? -ne 0 ] && [ -f /etc/redhat-release ]; then
    local redhat_release
    redhat_release=$(cat /etc/redhat-release | sed -e 's/^.* \([0-9]\+\)\..*$/\1/')

    if [ $redhat_release -eq 5 ]; then
      echo "we are on RHEL 5 and SELinux is old and doddery here :o)"
      echo -n "disabling SELinux... "
      sudo setenforce 0 && echo "done" || echo "fail"
      echo -n "trying again... "
      mv contains_many_entries contains_many_entries_renamed > /dev/null 2>&1 && echo "okay" || echo "fail"
      echo -n "enabling SELinux... "
      sudo setenforce 1 && echo "done" || echo "fail"
    fi
  fi

  popdir
}


cvmfs_run_test() {
  logfile=$1
  local repo_dir=/cvmfs/$CVMFS_TEST_REPO

  local scratch_dir=$(pwd)
  mkdir reference_dir
  local reference_dir=$scratch_dir/reference_dir

  echo "*** 1 create a fresh repository named $CVMFS_TEST_REPO with user $CVMFS_TEST_USER"
  create_empty_repo $CVMFS_TEST_REPO $CVMFS_TEST_USER || return $?

  echo "*** 1 starting transaction to edit repository (1)"
  start_transaction $CVMFS_TEST_REPO || return $?

  echo "*** 1 putting some stuff in the new repository"
  produce_initial_files_in $repo_dir || return 3

  echo "*** 1 putting exactly the same stuff in the scratch space for comparison"
  produce_initial_files_in $reference_dir || return 4

  echo "*** 1 creating CVMFS snapshot"
  publish_repo $CVMFS_TEST_REPO || return $?

  echo "*** 1 compare the results of cvmfs to our reference copy"
  compare_directories $repo_dir $reference_dir || return $?

  echo "*** 1 check catalog and data integrity"
  check_repository $CVMFS_TEST_REPO -i  || return $?

#
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
#

  echo "*** 2 starting transaction to edit repository (2)"
  start_transaction $CVMFS_TEST_REPO || return $?

  echo "*** 2 putting a new file in dir and rename dir"
  add_file_and_rename_parent $repo_dir || return 5

  echo "*** 2 doing exactly the same in the scratch space for comparison"
  add_file_and_rename_parent $reference_dir || return 6

  echo "*** 2 creating CVMFS snapshot"
  publish_repo $CVMFS_TEST_REPO || return $?

  echo "*** 2 compare the results of cvmfs to our reference copy"
  compare_directories $repo_dir $reference_dir || return $?

  echo "*** 2 check catalog and data integrity"
  check_repository $CVMFS_TEST_REPO -i  || return $?

#
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
#

  echo "*** 3 starting transaction to edit repository (3)"
  start_transaction $CVMFS_TEST_REPO || return $?

  echo "*** 3 removing a file from dir and renaming dir"
  remove_file_and_rename_parent $repo_dir || return 7

  echo "*** 3 doing exactly the same in the scratch space for comparison"
  remove_file_and_rename_parent $reference_dir || return 8

  echo "*** 3 creating CVMFS snapshot"
  publish_repo $CVMFS_TEST_REPO || return $?

  echo "*** 3 compare the results of cvmfs to our reference copy"
  compare_directories $repo_dir $reference_dir || return $?

  echo "*** 3 check catalog and data integrity"
  check_repository $CVMFS_TEST_REPO -i  || return $?

#
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
#

  echo "*** 4 starting transaction to edit repository (4)"
  start_transaction $CVMFS_TEST_REPO || return $?

  echo "*** 4 removing an empty directory in dir and renaming dir"
  remove_empty_directory_and_rename_parent $repo_dir || return 8

  echo "*** 4 doing exactly the same in the scratch space for comparison"
  remove_empty_directory_and_rename_parent $reference_dir || return 9

  echo "*** 4 creating CVMFS snapshot"
  publish_repo $CVMFS_TEST_REPO || return $?

  echo "*** 4 compare the results of cvmfs to our reference copy"
  compare_directories $repo_dir $reference_dir || return $?

  echo "*** 4 check catalog and data integrity"
  check_repository $CVMFS_TEST_REPO -i  || return $?

#
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
#

  echo "*** 5 starting transaction to edit repository (5)"
  start_transaction $CVMFS_TEST_REPO || return $?

  echo "*** 5 removing a non-empty directory in dir and rename dir"
  remove_directory_and_rename_parent $repo_dir || return 10

  echo "*** 5 doing exactly the same in the scratch space for comparison"
  remove_directory_and_rename_parent $reference_dir || return 11

  echo "*** 5 creating CVMFS snapshot"
  publish_repo $CVMFS_TEST_REPO || return $?

  echo "*** 5 compare the results of cvmfs to our reference copy"
  compare_directories $repo_dir $reference_dir || return $?

  echo "*** 5 check catalog and data integrity"
  check_repository $CVMFS_TEST_REPO -i  || return $?

#
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
#

  echo "*** 6 starting transaction to edit repository (6)"
  start_transaction $CVMFS_TEST_REPO || return $?

  echo "*** 6 removing an entry among others in dir and rename dir"
  remove_directory_among_many_entries_and_rename_parent $repo_dir || return 12

  echo "*** 6 doing exactly the same in the scratch space for comparison"
  remove_directory_among_many_entries_and_rename_parent $reference_dir || return 13

  echo "*** 6 creating CVMFS snapshot"
  publish_repo $CVMFS_TEST_REPO || return $?

  echo "*** 6 compare the results of cvmfs to our reference copy"
  compare_directories $repo_dir $reference_dir || return $?

  echo "*** 6 check catalog and data integrity"
  check_repository $CVMFS_TEST_REPO -i  || return $?

  return 0
}

