#!/bin/bash
cvmfs_test_name="Virtual .cvmfs Directory"
cvmfs_test_autofs_on_startup=false
cvmfs_test_suites="quick"

CVMFS_TEST638_REPLICA_NAME=

cleanup() {
  if [ "x$CVMFS_TEST638_REPLICA_NAME" != "x" ]; then
    sudo cvmfs_server rmfs -f $CVMFS_TEST638_REPLICA_NAME
  fi
}


check_no_create_virtualdir() {
  start_transaction $CVMFS_TEST_REPO || return $?
  touch /cvmfs/$CVMFS_TEST_REPO/.cvmfs || return 1
  publish_repo $CVMFS_TEST_REPO && return 2
  abort_transaction $CVMFS_TEST_REPO || return $?

  start_transaction $CVMFS_TEST_REPO || return $?
  ln -s . /cvmfs/$CVMFS_TEST_REPO/.cvmfs || return 10
  publish_repo $CVMFS_TEST_REPO && return 11
  abort_transaction $CVMFS_TEST_REPO || return $?

  start_transaction $CVMFS_TEST_REPO || return $?
  mkdir /cvmfs/$CVMFS_TEST_REPO/.cvmfs || return 20
  publish_repo $CVMFS_TEST_REPO && return 21
  abort_transaction $CVMFS_TEST_REPO || return $?

  start_transaction $CVMFS_TEST_REPO || return $?
  touch /cvmfs/$CVMFS_TEST_REPO/.CVMFS || return 30
  touch /cvmfs/$CVMFS_TEST_REPO/.cvmfs_allowed || return 30
  publish_repo $CVMFS_TEST_REPO || return 31
}


check_no_modify_virtualdir() {
  start_transaction $CVMFS_TEST_REPO || return $?
  sudo touch /cvmfs/$CVMFS_TEST_REPO/.cvmfs || return 30
  publish_repo $CVMFS_TEST_REPO && return 31
  abort_transaction $CVMFS_TEST_REPO || return $?

  start_transaction $CVMFS_TEST_REPO || return $?
  sudo touch /cvmfs/$CVMFS_TEST_REPO/.cvmfs/file || return 40
  publish_repo $CVMFS_TEST_REPO && return 41
  abort_transaction $CVMFS_TEST_REPO || return $?

  start_transaction $CVMFS_TEST_REPO || return $?
  sudo ln -s . /cvmfs/$CVMFS_TEST_REPO/.cvmfs/symlink || return 50
  publish_repo $CVMFS_TEST_REPO && return 51
  abort_transaction $CVMFS_TEST_REPO || return $?

  start_transaction $CVMFS_TEST_REPO || return $?
  sudo mkdir /cvmfs/$CVMFS_TEST_REPO/.cvmfs/dir || return 60
  publish_repo $CVMFS_TEST_REPO && return 61
  abort_transaction $CVMFS_TEST_REPO || return $?

  start_transaction $CVMFS_TEST_REPO || return $?
  sudo rm -rf /cvmfs/$CVMFS_TEST_REPO/.cvmfs || return 70
  publish_repo $CVMFS_TEST_REPO && return 71
  abort_transaction $CVMFS_TEST_REPO || return $?
}


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

  local scratch_dir=$(pwd)

  echo "--- (0) create a fresh repository named $CVMFS_TEST_REPO with user $CVMFS_TEST_USER"
  create_empty_repo $CVMFS_TEST_REPO $CVMFS_TEST_USER NO -g || return $?
  start_transaction $CVMFS_TEST_REPO || return $?
  mkdir /cvmfs/$CVMFS_TEST_REPO/nested || return 1
  touch /cvmfs/$CVMFS_TEST_REPO/nested/.cvmfscatalog || return 2
  publish_repo $CVMFS_TEST_REPO || return 3

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

  echo "--- (2) check that edits of .cvmfs are forbidden"
  check_no_create_virtualdir || return $?

  echo "--- (3) enable virtual directory"
  echo "CVMFS_VIRTUAL_DIR=true" | sudo tee -a /etc/cvmfs/repositories.d/$CVMFS_TEST_REPO/server.conf
  start_transaction $CVMFS_TEST_REPO || return $?
  touch /cvmfs/$CVMFS_TEST_REPO/dont_forget_me || return 20
  publish_repo $CVMFS_TEST_REPO -a tag_first || return $?
  ls -lah /cvmfs/$CVMFS_TEST_REPO/.cvmfs || return 21
  ls -lah /cvmfs/$CVMFS_TEST_REPO/dont_forget_me || return 22
  check_repository $CVMFS_TEST_REPO -i  || return 23

  echo "--- (4) check that edits of .cvmfs are still forbidden"
  check_no_modify_virtualdir || return $?

  echo "--- (5) reuse virtual directory"
  start_transaction $CVMFS_TEST_REPO || return $?
  publish_repo $CVMFS_TEST_REPO || return $?
  ls -lah /cvmfs/$CVMFS_TEST_REPO/.cvmfs || return 30
  check_repository $CVMFS_TEST_REPO -i || return 31

  echo "--- (6) look for content in virtual directory"
  local num_vdirs=$(ls /cvmfs/$CVMFS_TEST_REPO/.cvmfs/snapshots | wc -l)
  if [ $num_vdirs -lt 1 ]; then
    return 35
  fi

  echo "--- (7) ensure that special tag names are not listed"
  ls /cvmfs/$CVMFS_TEST_REPO/.cvmfs/snapshots/trunk && return 36
  ls /cvmfs/$CVMFS_TEST_REPO/.cvmfs/snapshots/trunk-previous && return 37

  echo "--- (8) ensure that garbage collection prunes bind mountpoints"
  echo "CVMFS_GARBAGE_COLLECTION=true" | \
    sudo tee -a /etc/cvmfs/repositories.d/$CVMFS_TEST_REPO/server.conf
  start_transaction $CVMFS_TEST_REPO || return $?
  publish_repo $CVMFS_TEST_REPO || return $?
  CVMFS_SERVER_DEBUG=3 cvmfs_server gc -lf $CVMFS_TEST_REPO 2>&1 | tee gc-s0.log || return 40
  grep "found root prefix /.cvmfs " gc-s0.log || return 41
  grep "/.cvmfs/snapshots" gc-s0.log && return 42
  check_repository $CVMFS_TEST_REPO -i || return 43

  echo "--- (9) ensure that bind mountpoints are not replicated"
  CVMFS_TEST638_REPLICA_NAME="$(get_stratum1_name $CVMFS_TEST_REPO)"
  load_repo_config $CVMFS_TEST_REPO
  trap cleanup EXIT HUP INT TERM
  create_stratum1 $CVMFS_TEST638_REPLICA_NAME                          \
                  $CVMFS_TEST_USER                       \
                  $CVMFS_STRATUM0                        \
                  /etc/cvmfs/keys/${CVMFS_TEST_REPO}.pub || return 51
  cvmfs_server snapshot $CVMFS_TEST638_REPLICA_NAME | tee snapshot.log || return 51
  grep "Replicating from catalog at /.cvmfs" snapshot.log || return 52
  grep "Replicating from catalog at /.cvmfs/" snapshot.log && return 53
  check_repository $CVMFS_TEST638_REPLICA_NAME -i || return 54
  CVMFS_SERVER_DEBUG=3 cvmfs_server gc -lf $CVMFS_TEST638_REPLICA_NAME 2>&1 | tee gc-s1.log || return 55
  grep "found root prefix /.cvmfs " gc-s1.log || return 56
  grep "/.cvmfs/snapshots" gc-s1.log && return 57
  check_repository $CVMFS_TEST638_REPLICA_NAME -i || return 58

  echo "--- (10) ensure that catalog-chown skips virtual catalog"
  local uid_before=$(stat -c %u /cvmfs/$CVMFS_TEST_REPO/.cvmfs/snapshots)
  local gid_before=$(stat -c %g /cvmfs/$CVMFS_TEST_REPO/.cvmfs/snapshots)
  [ "x$uid_before" != "x0" -o "x$gid_before" != "x0" ] && return 60
  echo "0 1" > uidmap
  echo "0 1" > gidmap
  sudo cvmfs_server catalog-chown -u uidmap -g gidmap $CVMFS_TEST_REPO || return 61
  local uid_after=$(stat -c %u /cvmfs/$CVMFS_TEST_REPO/.cvmfs/snapshots)
  local gid_after=$(stat -c %g /cvmfs/$CVMFS_TEST_REPO/.cvmfs/snapshots)
  [ "x$uid_after" != "x0" -o "x$gid_after" != "x0" ] && return 62
  check_repository $CVMFS_TEST_REPO -i || return 63

  echo "--- (11) creating some tags"
  start_transaction $CVMFS_TEST_REPO || return $?
  rm -f /cvmfs/$CVMFS_TEST_REPO/file-in-*
  touch /cvmfs/$CVMFS_TEST_REPO/file-in-tagx
  publish_repo $CVMFS_TEST_REPO -a tag_x || return $?
  start_transaction $CVMFS_TEST_REPO || return $?
  rm -f /cvmfs/$CVMFS_TEST_REPO/file-in-*
  touch /cvmfs/$CVMFS_TEST_REPO/file-in-tagy
  publish_repo $CVMFS_TEST_REPO -a tag_y || return $?
  start_transaction $CVMFS_TEST_REPO || return $?
  rm -f /cvmfs/$CVMFS_TEST_REPO/file-in-*
  touch /cvmfs/$CVMFS_TEST_REPO/file-in-tagz
  publish_repo $CVMFS_TEST_REPO -a tag_z || return $?
  ls /cvmfs/$CVMFS_TEST_REPO/.cvmfs/snapshots/tag_x/file-in-tagx || return 70
  ls /cvmfs/$CVMFS_TEST_REPO/.cvmfs/snapshots/tag_y/file-in-tagy || return 71
  ls /cvmfs/$CVMFS_TEST_REPO/.cvmfs/snapshots/tag_z/file-in-tagz || return 72
  check_repository $CVMFS_TEST_REPO -i || return 73

  echo "--- (12) test identical nested catalogs at different spots"
  tree /cvmfs/$CVMFS_TEST_REPO || return 80
  tree /cvmfs/$CVMFS_TEST_REPO/.cvmfs/snapshots || return 81
  local talk_socket=$(cat /etc/cvmfs/repositories.d/$CVMFS_TEST_REPO/client.conf | \
                      grep ^CVMFS_TALK_SOCKET= | cut -d= -f2)
  echo "cvmfs_talk socket path is $talk_socket"
  local num_open_nested=$(sudo cvmfs_talk -p $talk_socket open catalogs | grep nested | wc -l)
  if [ "x$num_open_nested" != "x5" ]; then
    echo "expected $num_open_nested = 5"
    sudo cvmfs_talk -p $talk_socket open catalogs
    sudo tail /var/log/messages
    return 82
  fi
  sudo cvmfs_talk -p $talk_socket detach nested catalogs || return 83
  local num_open_nested=$(sudo cvmfs_talk -p $talk_socket cache list pinned | grep nested | wc -l)
  if [ "x$num_open_nested" != "x0" ]; then
    return 84
  fi
  tree /cvmfs/$CVMFS_TEST_REPO || return 85
  tree /cvmfs/$CVMFS_TEST_REPO/.cvmfs/snapshots || return 86

  echo "--- (13) test creating/removing tags"
  local tag_x_hash=$(cvmfs_server tag -lx $CVMFS_TEST_REPO | grep -i tag_x | \
                     awk '{print $2}')
  cvmfs_server tag -a tag_rover -h $tag_x_hash $CVMFS_TEST_REPO || return 90
  tree /cvmfs/$CVMFS_TEST_REPO/.cvmfs/snapshots || return 91
  ls /cvmfs/$CVMFS_TEST_REPO/.cvmfs/snapshots/tag_rover/file-in-tagx || return 92
  cvmfs_server tag -r tag_z -f $CVMFS_TEST_REPO || return 93
  tree /cvmfs/$CVMFS_TEST_REPO/.cvmfs/snapshots || return 94
  ls /cvmfs/$CVMFS_TEST_REPO/.cvmfs/snapshots/tag_z && return 95
  check_repository $CVMFS_TEST_REPO -i || return 96

  echo "--- (13) test moving tags"
  local tag_y_hash=$(cvmfs_server tag -lx $CVMFS_TEST_REPO | grep -i tag_y | \
                     awk '{print $2}')
  cvmfs_server tag -a tag_rover -h $tag_y_hash $CVMFS_TEST_REPO || return 100
  tree /cvmfs/$CVMFS_TEST_REPO/.cvmfs/snapshots || return 101
  ls /cvmfs/$CVMFS_TEST_REPO/.cvmfs/snapshots/tag_rover/file-in-tagy || return 102
  check_repository $CVMFS_TEST_REPO -i || return 103

  echo "--- (14) removal of virtual catalog"
  echo "CVMFS_VIRTUAL_DIR=false" | sudo tee -a /etc/cvmfs/repositories.d/$CVMFS_TEST_REPO/server.conf
  start_transaction $CVMFS_TEST_REPO || return $?
  publish_repo $CVMFS_TEST_REPO -v || return $?
  check_repository $CVMFS_TEST_REPO -i || return 100
  tree /cvmfs/$CVMFS_TEST_REPO || 101
  ls /cvmfs/$CVMFS_TEST_REPO/nested || return 102
  ls /cvmfs/$CVMFS_TEST_REPO/.cvmfs && return 103

  return 0
}
