#!/bin/bash
cvmfs_test_name="Magic Symlinks"
cvmfs_test_autofs_on_startup=false
cvmfs_test_suites="quick"

produce_files_in_1() {
  local working_dir=$1

  pushdir $working_dir

  mkdir -p 'foo/1.0' 'foo/1.1' 'foo/1.2'
  mkdir -p 'bar/2.0' 'bar/2.1' 'bar/2.2'

  for d in $(find . -mindepth 2 -type d); do
    head -c 10 /dev/urandom > ${d}/f
    head -c 10 /dev/urandom > ${d}/g
    head -c 10 /dev/urandom > ${d}/h
  done

  ln -s 'foo' foo_dir
  ln -s 'bar' bar_dir

  ln -s '$(FOO_VERSION)' foo/current
  ln -s '$(BAR_VERSION)' bar/current

  ln -s '$(PROGRAM_TYPE)/current' bin

  ln -s '$(PROGRAM_TYPE)/$(GENERIC_VERSION)' general

  touch foo/.cvmfscatalog

  popdir
}

produce_files_in_2() {
  local working_dir=$1

  pushdir $working_dir

  touch foo/1.0/.cvmfscatalog
  touch foo/1.1/.cvmfscatalog
  touch foo/1.2/.cvmfscatalog

  touch bar/.cvmfscatalog

  popdir
}

produce_files_in_3() {
  local working_dir=$1

  pushdir $working_dir

  rm -f foo/.cvmfscatalog
  rm -f bar/.cvmfscatalog

  touch bar/2.0/.cvmfscatalog
  touch bar/2.1/.cvmfscatalog
  touch bar/2.2/.cvmfscatalog

  popdir
}


setup_environment_variables_1() {
  export FOO_VERSION=1.2
  export BAR_VERSION=2.1
  export PROGRAM_TYPE=foo
  export GENERIC_VERSION=1.1
}

setup_environment_variables_2() {
  export FOO_VERSION=1.0
  export BAR_VERSION=2.2
  export PROGRAM_TYPE=bar
  export GENERIC_VERSION=2.1
}

setup_environment_variables_3() {
  export FOO_VERSION=1.1
  export BAR_VERSION=2.0
  export PROGRAM_TYPE=foo
  export GENERIC_VERSION=1.0
}


print_envionment_variables() {
  echo "\$FOO_VERSION     = $FOO_VERSION"
  echo "\$BAR_VERSION     = $BAR_VERSION"
  echo "\$PROGRAM_TYPE    = $PROGRAM_TYPE"
  echo "\$GENERIC_VERSION = $GENERIC_VERSION"
}


check_symlink() {
  local symlink_path="$1"
  local expected_link="$2"

  if [ ! -h $symlink_path ]; then
    echo "symlink '$symlink_path' doesn't exist"
    return 1
  fi

  local link_content=
  link_content=$(readlink $symlink_path)
  if [ $? != 0 ]; then
    echo "failed to read link value for '$symlink_path'"
    return 2
  fi

  if [ x"$link_content" != x"$expected_link" ]; then
    echo "symlink doesn't have the expected content"
    echo "expected: $expected_link"
    echo "found:    $link_content"
    return 3
  fi
}


check_symlinks() {
  local mountpoint="$1"
  check_symlink "${mountpoint}/bar/current" "${BAR_VERSION}"                     || return 1
  check_symlink "${mountpoint}/foo/current" "${FOO_VERSION}"                     || return 2
  check_symlink "${mountpoint}/bin"         "${PROGRAM_TYPE}/current"            || return 3
  check_symlink "${mountpoint}/general"     "${PROGRAM_TYPE}/${GENERIC_VERSION}" || return 4
}


TEST_592_MOUNTPOINT=""
cleanup() {
  if [ ! -z $TEST_592_MOUNTPOINT ]; then
    echo -n "umounting ${TEST_592_MOUNTPOINT}... "
    remove_local_mount $TEST_592_MOUNTPOINT && echo "done" || echo "fail"
  fi
}


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

  local scratch_dir=$(pwd)

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

  echo "starting transaction to edit repository"
  start_transaction $CVMFS_TEST_REPO || return $?

  echo "putting some stuff in the new repository"
  produce_files_in_1 $repo_dir || return 1

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

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

  echo "set a trap for desaster cleanup"
  trap cleanup EXIT HUP INT TERM

  echo "set up environment variables"
  setup_environment_variables_1 || return 2
  print_envionment_variables    || return 3

  echo "create a local mount of the created repository"
  TEST_592_MOUNTPOINT="$(pwd)/local_mount"
  do_local_mount "$TEST_592_MOUNTPOINT" \
                 "$CVMFS_TEST_REPO"     \
                 "$(get_repo_url $CVMFS_TEST_REPO)" || return 4

  echo "check magic symlinks"
  check_symlinks "$TEST_592_MOUNTPOINT" || return 5

  echo "ensure raw symlinks in server mode"
  check_symlinks "/var/spool/cvmfs/${CVMFS_TEST_REPO}/rdonly"
  if [ $? -eq 0 ]; then
    return 30
  fi

  echo "umount private mount"
  remove_local_mount $TEST_592_MOUNTPOINT || return 6

  echo "open transaction to fiddle with nested catalogs"
  start_transaction $CVMFS_TEST_REPO || return $?

  echo "change repository structure"
  produce_files_in_2 $repo_dir || return 7

  echo "publish changes"
  publish_repo $CVMFS_TEST_REPO || return $?

  echo "set up new environment variables"
  setup_environment_variables_2 || return 8
  print_envionment_variables    || return 9

  echo "create a local mount of the created repository"
  do_local_mount "$TEST_592_MOUNTPOINT" \
                 "$CVMFS_TEST_REPO"     \
                 "$(get_repo_url $CVMFS_TEST_REPO)" || return 10

  echo "check magic symlinks"
  check_symlinks $TEST_592_MOUNTPOINT || return 11

  echo "umount private mount"
  remove_local_mount $TEST_592_MOUNTPOINT || return 12

  echo "open transaction to fiddle with nested catalogs"
  start_transaction $CVMFS_TEST_REPO || return $?

  echo "change repository structure"
  produce_files_in_3 $repo_dir || return 13

  echo "publish changes"
  publish_repo $CVMFS_TEST_REPO || return $?

  echo "set up new environment variables"
  setup_environment_variables_3 || return 14
  print_envionment_variables    || return 15

  echo "create a local mount of the created repository"
  do_local_mount "$TEST_592_MOUNTPOINT" \
                 "$CVMFS_TEST_REPO"     \
                 "$(get_repo_url $CVMFS_TEST_REPO)" || return 16

  echo "check magic symlinks"
  check_symlinks $TEST_592_MOUNTPOINT || return 17

  return 0
}

