The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
# This file describe operations needed for migration between versions,
# both for UPGRADE and DOWNGRADE.
#
# Documentation about syntax of this file:
# https://metacpan.org/pod/App::migrate#SYNTAX
#
# You shouldn't modify anything in this file BEFORE LAST "VERSION" LINE!
# If you will do this you'll likely BREAK DOWNGRADE for some version.
# Exceptions from this rule are:
# - git rebase
# - add/remove comments, empty lines or do other visual/formatting changes
# - add new DEFINEs
# - modification of downgrade/after_downgrade operations needed to FIX
#   BROKEN DOWNGRADE
#
# You shouldn't manually add "VERSION" lines - run narada-release instead.
# Exceptions from this rule are some advanced use cases like:
# - squashing several patches into one
# - merging different release branches like 1.x and 2.x


# INSTALL
# - usually it will be automatically added by ./release, and you shouldn't
#   add it manually
# - this operation must be the last one, right before VERSION - to make
#   sure patch&tgz will be applied exactly between before_upgrade and
#   upgrade operations, and will be reversed exactly between downgrade and
#   after_downgrade operations
DEFINE2 INSTALL
before_upgrade
  if test -f .release/${MIGRATE_NEXT_VERSION}.patch; then
    GIT_DIR=.git git apply .release/${MIGRATE_NEXT_VERSION}.patch
  fi
  if test -f .release/${MIGRATE_PREV_VERSION}.tgz; then
    files='m{\A[.]/\n}&&next;s/\n/\0/;s/(\\.)/"\"$1\""/gee;m{/\0}||print'
     dirs='m{\A[.]/\n}&&next;s/\n/\0/;s/(\\.)/"\"$1\""/gee;m{/\0}&&print'
    names=$(tar tzf .release/${MIGRATE_PREV_VERSION}.tgz)
    echo "$names" |       perl -ne "$files" | xargs -0 -r rm -f
    echo "$names" | tac | perl -ne "$dirs"  | xargs -0 -r rmdir --ignore-fail-on-non-empty
  fi
  if test -f .release/${MIGRATE_NEXT_VERSION}.tgz; then
    tar xzvpf .release/${MIGRATE_NEXT_VERSION}.tgz
  fi
  narada-bg-killall
after_downgrade
  if test -f .release/${MIGRATE_PREV_VERSION}.patch; then
    GIT_DIR=.git git apply -R .release/${MIGRATE_PREV_VERSION}.patch
  fi
  if test -f .release/${MIGRATE_PREV_VERSION}.tgz; then
    files='m{\A[.]/\n}&&next;s/\n/\0/;s/(\\.)/"\"$1\""/gee;m{/\0}||print'
     dirs='m{\A[.]/\n}&&next;s/\n/\0/;s/(\\.)/"\"$1\""/gee;m{/\0}&&print'
    names=$(tar tzf .release/${MIGRATE_PREV_VERSION}.tgz)
    echo "$names" |       perl -ne "$files" | xargs -0 -r rm -f
    echo "$names" | tac | perl -ne "$dirs"  | xargs -0 -r rmdir --ignore-fail-on-non-empty
  fi
  if test -f .release/${MIGRATE_NEXT_VERSION}.tgz; then
    tar xzvpf .release/${MIGRATE_NEXT_VERSION}.tgz
  fi
  narada-bg-killall

DEFINE2 only_before_upgrade
upgrade
downgrade true

DEFINE2 only_upgrade
upgrade
downgrade true

DEFINE2 only_downgrade
upgrade true
downgrade

DEFINE2 only_after_downgrade
upgrade true
after_downgrade

# mysql path/to/alter.sql
# mysql
#   sql commands here ...
DEFINE mysql
upgrade
  test -f "$1" -a -r "$1"
  narada-mysql < "$1"

# rollback_mysql path/to/alter.sql
# rollback_mysql
#   sql commands here ...
DEFINE rollback_mysql
downgrade
  test -f "$1" -a -r "$1"
  narada-mysql < "$1"

# mkdir some/dir ...
# - parameters can't contain /../ or begin with /
DEFINE2 mkdir
upgrade
  perl -e 'exit grep {m{\A/|(\A|/)[.][.](/|\z)}} @ARGV' "$@"
  mkdir "$@"
downgrade
  perl -e 'exit grep {m{\A/|(\A|/)[.][.](/|\z)}} @ARGV' "$@"
  rm -rf "$@"

# rmdir some/dir ...
# - parameters can't contain /../ or begin with /
DEFINE2 rmdir
upgrade
  perl -e 'exit grep {m{\A/|(\A|/)[.][.](/|\z)}} @ARGV' "$@"
  rm -rf "$@"
after_downgrade
  perl -e 'exit grep {m{\A/|(\A|/)[.][.](/|\z)}} @ARGV' "$@"
  narada-restore .backup/full-"$MIGRATE_NEXT_VERSION".tar "$@"

# rm some/file ...
# - parameters can't contain /../ or begin with /
DEFINE2 rm
upgrade
  perl -e 'exit grep {m{\A/|(\A|/)[.][.](/|\z)}} @ARGV' "$@"
  rm -f "$@"
after_downgrade
  perl -e 'exit grep {m{\A/|(\A|/)[.][.](/|\z)}} @ARGV' "$@"
  narada-restore .backup/full-"$MIGRATE_NEXT_VERSION".tar "$@"

# add_config some/config "value"
# add_config some/config -
#   value
# - config must not exists
DEFINE2 add_config
upgrade
  test ! -e config/"$1"
  mkdir -p $(dirname config/"$1")
  { test $# = 3 && cat "$3" || echo -n "$2"; } > config/"$1"
  # echo "$1" | grep -v -q '^crontab/' || narada-setup-cron
  # echo "$1" | grep -v -q '^qmail/'   || narada-setup-qmail
downgrade
  rm -f config/"$1"
  rmdir -p $(dirname config/"$1") 2>/dev/null || :
  # echo "$1" | grep -v -q '^crontab/' || narada-setup-cron
  # echo "$1" | grep -v -q '^qmail/'   || narada-setup-qmail

# set_config some/config "new value"
# set_config some/config -
#   new value
# - config may exists
# - on downgrade previous value restored only if current is "new value"
DEFINE2 set_config
upgrade
  mkdir -p $(dirname config/"$1")
  { test $# = 3 && cat "$3" || echo -n "$2"; } > config/"$1"
  # echo "$1" | grep -v -q '^crontab/' || narada-setup-cron
  # echo "$1" | grep -v -q '^qmail/'   || narada-setup-qmail
after_downgrade
  test $# = 3 && value=$(cat "$3") || value="$2"
  if test "$(cat config/"$1")" = "$value"; then
    narada-restore .backup/full-"$MIGRATE_NEXT_VERSION".tar config/"$1"
    # echo "$1" | grep -v -q '^crontab/' || narada-setup-cron
    # echo "$1" | grep -v -q '^qmail/'   || narada-setup-qmail
  fi

# mod_config some/config "pcre regex" "new value"
# mod_config some/config "pcre regex" -
#   new value
# - config must exists
# - value changed only if current value match "pcre regex"
# - on downgrade previous value restored only if current is "new value"
DEFINE2 mod_config
upgrade
  test -e config/"$1"
  if grep -q -P -- "$2" config/"$1"; then
    { test $# = 4 && cat "$4" || echo -n "$3"; } > config/"$1"
    # echo "$1" | grep -v -q '^crontab/' || narada-setup-cron
    # echo "$1" | grep -v -q '^qmail/'   || narada-setup-qmail
  fi
after_downgrade
  test $# = 4 && value=$(cat "$4") || value="$3"
  if test "$(cat config/"$1")" = "$value"; then
    narada-restore .backup/full-"$MIGRATE_NEXT_VERSION".tar config/"$1"
    # echo "$1" | grep -v -q '^crontab/' || narada-setup-cron
    # echo "$1" | grep -v -q '^qmail/'   || narada-setup-qmail
  fi

# del_config some/config
DEFINE2 del_config
upgrade
  rm -f config/"$1"
  rmdir -p $(dirname config/"$1") 2>/dev/null || :
  # echo "$1" | grep -v -q '^crontab/' || narada-setup-cron
  # echo "$1" | grep -v -q '^qmail/'   || narada-setup-qmail
after_downgrade
  narada-restore .backup/full-"$MIGRATE_NEXT_VERSION".tar config/"$1"
  # echo "$1" | grep -v -q '^crontab/' || narada-setup-cron
  # echo "$1" | grep -v -q '^qmail/'   || narada-setup-qmail

# exclude_from_backup "value"
DEFINE2 exclude_from_backup
upgrade
  test -e config/backup/exclude
  if ! grep -q -F -x -- "$1" config/backup/exclude; then
    echo "$1" >> config/backup/exclude
  fi
after_downgrade
  test -e config/backup/exclude
  grep -v -F -x -- "$1" config/backup/exclude >tmp/config_backup_exclude.$$
  mv tmp/config_backup_exclude.$$ config/backup/exclude

# kill process_name ...
# - make sure processes started before upgrade/downgrade but blocked on
#   start because of lock won't continue to run after upgrade/downgrade
DEFINE2 kill
upgrade
  killall -9 "$@" || :
after_downgrade
  killall -9 "$@" || :


# Initial version. MUST be 0.0.0 for new empty projects.
VERSION 0.0.0


# REQUIRED Narada files & directories:
only_upgrade
    mkdir -p .backup
mkdir config
mkdir tmp
mkdir var
mkdir var/log
mkdir var/use

add_config backup/exclude -
  ./.backup/*
  ./.lock*
  ./tmp/*
  ./.release/*
add_config crontab/backup -
  1 3 * * *   ( narada-backup && echo Reminder: encrypt .backup/full.tar with config/backup/pass and upload it somewhere >&2) >/dev/null
  1 2 * * 1   rm .backup/full.tar >/dev/null 2>&1

add_config log/level    DEBUG
add_config log/type     file
add_config log/output   var/log/default.log


# OPTIONAL Narada files & directories:
mkdir config/qmail
mkdir var/mysql
mkdir var/qmail

add_config mysql/host
add_config mysql/port 3306
add_config mysql/db
add_config mysql/login
add_config mysql/pass
add_config mysql/dump/empty
add_config mysql/dump/ignore
add_config mysql/dump/incremental


INSTALL
VERSION 0.1.0


### narada-plugin-runit

# restart service_to_restart
DEFINE2 restart
upgrade
  sv t ./service/"$1" || :
after_downgrade
  sv t ./service/"$1" || :

add_config service/type runit
# add_config crontab/service -
#   */1  * * * *    narada-start-services &


### narada-plugin-socklog

set_config log/type     syslog
set_config log/output   var/log.sock

# restart log


INSTALL
VERSION 0.2.0