Only update start_erl.data if detecting ERTS

See #217

#!/bin/sh

set -e

# Set VERBOSE to enable verbose logging of the boot script
#VERBOSE=true
if [ ! -z $DEBUG_BOOT ]; then
    set -x
fi;

my_readlink_f() {
    TARGET_FILE="$1"
    cd $(dirname "$TARGET_FILE")
    TARGET_FILE=$(basename "$TARGET_FILE")

    # Iterate down a (possible) chain of symlinks
    while [ -L "$TARGET_FILE" ]
    do
        TARGET_FILE=$(readlink "$TARGET_FILE")
        cd $(dirname "$TARGET_FILE")
        TARGET_FILE=$(basename "$TARGET_FILE")
    done
    # Compute the canonicalized name by finding the physical path
    # for the directory we're in and appending the target file.
    PHYS_DIR=$(pwd -P)
    RESULT="$PHYS_DIR/$TARGET_FILE"
    echo "$RESULT"
}

# Path to this script
if uname | grep -q 'Darwin'; then
  # on OSX, best to install coreutils from homebrew or similar
  # to get greadlink
  if command -v greadlink >/dev/null 2>&1; then
    SCRIPT="${SCRIPT:-$(greadlink -f "$0")}"
  else
    SCRIPT="${SCRIPT:-$(my_readlink_f "$0")}"
  fi
else
  SCRIPT="${SCRIPT:-$(readlink -f "$0" )}"
fi

# Parent directory of this script
SCRIPT_DIR="${SCRIPT_DIR:-$(dirname "${SCRIPT}")}"
# Root directory of all releases
RELEASE_ROOT_DIR="${RELEASE_ROOT_DIR:-$(dirname $(dirname ${SCRIPT_DIR}))}"

# Disable flow control for run_erl
# Flow control can cause several problems. On Linux, if you
# accidentally hit Ctrl-S (instead of Ctrl-D to detach) and
# then some other key, the entire beam process will hang when
# attempting to write to stdout. On Solaris, the beam process
# will hang on writing if ScrollLock is on.
RUN_ERL_DISABLE_FLOWCNTRL="${RUN_ERL_DISABLE_FLOWCNTRL:-true}"
# Name of the release
REL_NAME="${REL_NAME:-<%= release_name %>}"
# Current version of the release
REL_VSN="${REL_VSN:-<%= release_version %>}"
# Current version of ERTS being used
# If this is not present/unset, it will be detected
<%= if ((is_binary(include_erts) or include_erts) and not is_nil(erts_vsn)) do %>ERTS_VSN="${ERTS_VSN:-<%= erts_vsn %>}"<% end %>
# VM code loading mode, embedded by default, can also be interactive
# See http://erlang.org/doc/man/code.html
CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}"
# Path to start_erl.data
START_ERL_DATA="${START_ERL_DATA:-$RELEASE_ROOT_DIR/releases/start_erl.data}"
# Directory containing the current version of this release
REL_DIR="${REL_DIR:-$RELEASE_ROOT_DIR/releases/$REL_VSN}"
# The lib directory for this release
REL_LIB_DIR="${REL_LIB_DIR:-$RELEASE_ROOT_DIR/lib}"
# Options passed to erl
ERL_OPTS="${ERL_OPTS:-<%= release.profile.erl_opts %>}"
# When stdout is piped to a file, this is the directory those files will
# be stored in. defaults to /log in the release root directory

# RELEASE_MUTABLE_DIR
RELEASE_MUTABLE_DIR="${RELEASE_MUTABLE_DIR:-$RELEASE_ROOT_DIR/var}"

RUNNER_LOG_DIR="${RUNNER_LOG_DIR:-$RELEASE_MUTABLE_DIR/log}"
# A string of extra options to pass to erl, here for plugins
EXTRA_OPTS="${EXTRA_OPTS:-}"

# Pre-start/stop event hook paths
PRE_CONFIGURE_HOOKS="$REL_DIR/hooks/pre_configure.d"
PRE_START_HOOKS="$REL_DIR/hooks/pre_start.d"
POST_START_HOOKS="$REL_DIR/hooks/post_start.d"
PRE_STOP_HOOKS="$REL_DIR/hooks/pre_stop.d"
POST_STOP_HOOKS="$REL_DIR/hooks/post_stop.d"
PRE_UPGRADE_HOOKS="$REL_DIR/hooks/pre_upgrade.d"
POST_UPGRADE_HOOKS="$REL_DIR/hooks/post_upgrade.d"

# Get node pid
get_pid() {
    if output="$(nodetool rpcterms os getpid)"
    then
        echo "$output" | sed -e 's/"//g'
        return 0
    else
        echo "$output"
        return 1
    fi
}

# Generate a unique nodename
gen_nodename() {
    id="longname$(gen_id)-${NAME}"
    "$BINDIR/erl" -boot start_clean -eval '[Host] = tl(string:tokens(atom_to_list(node()),"@")), io:format("~s~n", [Host]), halt()' -noshell ${NAME_TYPE} $id
}

# Generate a random id
gen_id() {
    od -t x -N 4 /dev/urandom | head -n1 | awk '{print $2}'
}

# Control a node
# Use like `nodetool "ping"`
nodetool() {
    command="$1"; shift
    name=${PEERNAME:-$NAME}
    "$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$name" \
                            -setcookie "$COOKIE" "$command" $@
}

# Run an escript in the node's environment
# Use like `escript "path/to/escript"`
escript() {
    shift; scriptpath="$1"; shift
    export RELEASE_ROOT_DIR

    "$ERTS_DIR/bin/escript" "$ROOTDIR/$scriptpath" $@
}

# Private. Load target cookie, either from vm.args or $HOME/.cookie
_load_cookie() {
    COOKIE_ARG="$(grep '^-setcookie' "$VMARGS_PATH" || true)"
    DEFAULT_COOKIE_FILE="$HOME/.erlang.cookie"
    if [ -z "$COOKIE_ARG" ]; then
        if [ -f "$DEFAULT_COOKIE_FILE" ]; then
            COOKIE="$(cat "$DEFAULT_COOKIE_FILE")"
        fi
    else
        # Extract cookie name from COOKIE_ARG
        COOKIE="$(echo "$COOKIE_ARG" | awk '{print $2}')"
    fi
}

# Private. Ensure that cookie is set.
_check_cookie() {
    # Attempt reloading cookie in case it has been set in a hook
    if [ -z "$COOKIE" ]; then
        _load_cookie
    fi
    # Die if cookie is still not set, as connecting via distribution will fail
    if [ -z "$COOKIE" ]; then
        printf "a secret cookie must be provided in one of the following ways:\n  - with vm.args using the -setcookie parameter,\n  or\n  by writing the cookie to '$DEFAULT_COOKIE_FILE', with permissions set to 0400"
        exit 1
    fi
}

# Private. For setting up the Erlang runtime to use
_init_erts_config() {
    if [ -z "$ERTS_VSN" ]; then
        set +e # temporarily disable so we can display a nice error message to the user
        __erl="$(which erl)"
        set -e
        if [ -z "${__erl}"  ]; then
            echo 'erlang runtime not found. If erlang is installed check your $PATH. aborting.'
            exit 1
        fi
        export ROOTDIR="$("$__erl" -boot start_clean -eval 'io:format("~s~n", [code:root_dir()]), halt().' -noshell)"
        export ERTS_VSN="$(_get_erts_vsn)"
        export ERTS_DIR="$ROOTDIR"/"erts-$ERTS_VSN"
        # Update start_erl.data
        echo "$ERTS_VSN $REL_VSN" > "$START_ERL_DATA"
    else
        __erts_dir="$RELEASE_ROOT_DIR/erts-$ERTS_VSN"
        if [ -d "$__erts_dir" ]; then
            export ROOTDIR="$RELEASE_ROOT_DIR"
            export ERTS_DIR="$__erts_dir"
        else
            unset ERTS_VSN
            _init_erts_config
        fi
    fi
}

# Private. For determining the version of ERTS available to the release
# This is only ever called if ERTS_VSN is not set
_get_erts_vsn() {
    if [ -z "$ERTS_VSN" ]; then
        "$ROOTDIR"/bin/erl \
            -boot start_clean \
            -eval 'Ver = erlang:system_info(version), io:format("~s~n", [Ver]), halt()' \
            -noshell
    else
        echo "$ERTS_VSN"
    fi
}

# Private. Gets a list of code paths for this release
_get_code_paths() {
    "$ERTS_DIR/bin/escript" "$ROOTDIR/bin/release_utils.escript" "get_code_paths" "$ROOTDIR" "$ERTS_DIR" "$REL_NAME" "$REL_VSN"
}

# Private. Open a shell on a remote node
_rem_sh() {
    # Generate a unique id used to allow multiple remsh to the same node
    # transparently
    id="remsh$(gen_id)-${NAME}"

    # Get the node's ticktime so that we use the same thing.
    TICKTIME="$(nodetool rpcterms net_kernel get_net_ticktime)"

    # Setup remote shell command to control node
    if [ ! -z "$USE_ERL_SHELL" ]; then
        exec "$BINDIR/erl" \
            -hidden \
            -boot start_clean -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -kernel net_ticktime $TICKTIME \
            "$NAME_TYPE" "$id" -remsh "$NAME" -setcookie "$COOKIE"
    else
        __code_paths=$(_get_code_paths)
        exec "$BINDIR/erl" \
            -pa "$CONSOLIDATED_DIR" \
            ${__code_paths} \
            -hidden -noshell \
            -boot start_clean -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -kernel net_ticktime $TICKTIME \
            -user Elixir.IEx.CLI "$NAME_TYPE" "$id" -setcookie "$COOKIE" \
            -extra --no-halt +iex -"$NAME_TYPE" "$id" --cookie "$COOKIE" --remsh "$NAME"
    fi
}

# Output a start command for the last argument of run_erl
_start_command() {
    printf "exec \"%s\" \"%s\" -- %s %s" "$RELEASE_ROOT_DIR/bin/$REL_NAME" \
           "$START_OPTION" "${ARGS}" "${EXTRA_OPTS}"
}

# Do a textual replacement of ${VAR} occurrences in $1 and pipe to $2
_replace_os_vars() {
    awk '
        function escape(s) {
            gsub(/'\&'/, "\\\\&", s);
            return s;
        }
        {
            while(match($0,"[$]{[^}]*}")) {
                var=substr($0,RSTART+2,RLENGTH-3);
                gsub("[$]{"var"}", escape(ENVIRON[var]))
            }
        }1' < "$1" > "$1.bak"
    mv -- "$1.bak" "$1"
}

# Private. Run hooks from directory.
_run_hooks_from_dir() {
   if [ -d "$1" ]; then
      for file in $1/[0-9a-zA-Z]*.sh; do
        [ -f "$file" ] || continue
        . "$file"
      done
   fi
}

# Private. Sets config paths for sys.config and vm.args,
# and ensures that env var replacements are performed
_init_configs() {
    # Set VMARGS_PATH, the path to the vm.args file to use
    # Use $RELEASE_CONFIG_DIR/vm.args if exists, otherwise releases/VSN/vm.args
    if [ -z "$VMARGS_PATH" ]; then
        if [ -f "$RELEASE_CONFIG_DIR/vm.args" ]; then
            export VMARGS_PATH="$RELEASE_CONFIG_DIR/vm.args"
        else
            export VMARGS_PATH="$REL_DIR/vm.args"
        fi
        export SRC_VMARGS_PATH="$VMARGS_PATH"
    else
        if [ "$VMARGS_PATH" != "$RELEASE_MUTABLE_DIR/vm.args" ]; then
            export SRC_VMARGS_PATH="$VMARGS_PATH"
        else
            if [ -f "$RELEASE_CONFIG_DIR/vm.args" ]; then
                export VMARGS_PATH="$RELEASE_CONFIG_DIR/vm.args"
            else
                export VMARGS_PATH="$REL_DIR/vm.args"
            fi
            export SRC_VMARGS_PATH="$VMARGS_PATH"
        fi
    fi
    if [ "$SRC_VMARGS_PATH" != "$RELEASE_MUTABLE_DIR/vm.args" ]; then
        echo "#### Generated - edit/create $RELEASE_CONFIG_DIR/vm.args instead." \
            >  "$RELEASE_MUTABLE_DIR/vm.args"
        cat  "$SRC_VMARGS_PATH"                              \
            >> "$RELEASE_MUTABLE_DIR/vm.args"
        export VMARGS_PATH="$RELEASE_MUTABLE_DIR"/vm.args
    fi
    if [ $REPLACE_OS_VARS ]; then
        _replace_os_vars "$VMARGS_PATH"
    fi

    # Set SYS_CONFIG_PATH, the path to the sys.config file to use
    # Use $RELEASE_CONFIG_DIR/sys.config if exists, otherwise releases/VSN/sys.config
    if [ -z "$SYS_CONFIG_PATH" ]; then
        if [ -f "$RELEASE_CONFIG_DIR/sys.config" ]; then
            export SYS_CONFIG_PATH="$RELEASE_CONFIG_DIR/sys.config"
        else
            export SYS_CONFIG_PATH="$REL_DIR/sys.config"
        fi
        export SRC_SYS_CONFIG_PATH="$SYS_CONFIG_PATH"
    else
        if [ "$SYS_CONFIG_PATH" != "$RELEASE_MUTABLE_DIR/sys.config" ]; then
            export SRC_SYS_CONFIG_PATH="$SYS_CONFIG_PATH"
        else
            if [ -f "$RELEASE_CONFIG_DIR/sys.config" ]; then
                export SYS_CONFIG_PATH="$RELEASE_CONFIG_DIR/sys.config"
            else
                export SYS_CONFIG_PATH="$REL_DIR/sys.config"
            fi
            export SRC_SYS_CONFIG_PATH="$SYS_CONFIG_PATH"
        fi
    fi
    if [ "$SRC_SYS_CONFIG_PATH" != "$RELEASE_MUTABLE_DIR/sys.config" ]; then
        (echo "%% Generated - edit/create $RELEASE_CONFIG_DIR/sys.config instead."; \
        cat  "$SRC_SYS_CONFIG_PATH")                              \
            > "$RELEASE_MUTABLE_DIR/sys.config"
        export SYS_CONFIG_PATH="$RELEASE_MUTABLE_DIR"/sys.config
    fi
    if [ $REPLACE_OS_VARS ]; then
        _replace_os_vars "$SYS_CONFIG_PATH"
    fi
}

# If TERM is not set, set it to xterm
if [ -z "$TERM" ]; then
    export TERM=xterm
fi

# Make sure ERTS configuration is set
_init_erts_config

# Allow override of where to read configuration from
# By default it's RELEASE_ROOT_DIR
if [ -z "$RELEASE_CONFIG_DIR" ]; then
    export RELEASE_CONFIG_DIR="$RELEASE_ROOT_DIR"
fi

# Make sure directories exist
mkdir -p "$RELEASE_MUTABLE_DIR"
echo "Files in this directory are regenerated frequently, edits will be lost" \
    > "$RELEASE_MUTABLE_DIR/WARNING_README"
mkdir -p "$RUNNER_LOG_DIR"

# Make sure config paths are setup
_init_configs

# Extract the target node name from node.args
# Should be `-sname somename` or `-name somename@somehost`
export NAME_ARG="$(egrep '^-s?name' "$VMARGS_PATH" || true)"
if [ -z "$NAME_ARG" ]; then
    echo "vm.args needs to have either -name or -sname parameter."
    exit 1
fi

# Extract the name type and name from the NAME_ARG for REMSH
# NAME_TYPE should be -name or -sname
export NAME_TYPE="$(echo "$NAME_ARG" | awk '{print $1}')"
# NAME will be either `somename` or `somename@somehost`
export NAME="$(echo "$NAME_ARG" | awk '{print $2}')"

# Where the pipe will be stored when using `start`
# This is used so you can attach the running application to the current
# shell using `attach`
PIPE_DIR="${PIPE_DIR:-$RELEASE_MUTABLE_DIR/erl_pipes/$NAME/}"

# Extract the target cookie
_load_cookie

export ROOTDIR="$RELEASE_ROOT_DIR"
export BINDIR="$ERTS_DIR/bin"
export EMU="beam"
export PROGNAME="erl"
export LD_LIBRARY_PATH="$ERTS_DIR/lib:$LD_LIBRARY_PATH"
export ERTS_LIB_DIR="$ERTS_DIR/../lib"
CONSOLIDATED_DIR="$ROOTDIR/lib/${REL_NAME}-${REL_VSN}/consolidated"

cd "$ROOTDIR"

# User can specify an sname without @hostname
# This will fail when creating remote shell
# So here we check for @ and add @hostname if missing
case $NAME in
    *@*)
        # Nothing to do
        ;;
    *)
        NAME=$NAME@$(gen_nodename)
        ;;
esac

# For Elixir runtime
export DISTILLERY_TASK="$1"

# Check the first argument for instructions
case "$1" in
    start|start_boot)

        # Make sure there is not already a node running
        #RES=`$NODETOOL ping`
        #if [ "$RES" = "pong" ]; then
        #    echo "Node is already running!"
        #    exit 1
        #fi
        # Save this for later.
        CMD=$1
        case "$1" in
            start)
                shift
                START_OPTION="console"
                HEART_OPTION="start"
                ;;
            start_boot)
                shift
                START_OPTION="console_boot"
                HEART_OPTION="start_boot"
                ;;
        esac
        ARGS="$@"
        RUN_PARAM="$@"

        _check_cookie
        _run_hooks_from_dir "$PRE_CONFIGURE_HOOKS"
        _run_hooks_from_dir "$PRE_START_HOOKS"

        # Set arguments for the heart command
        set -- "$SCRIPT_DIR/$REL_NAME" "$HEART_OPTION"
        [ "$RUN_PARAM" ] && set -- "$@" "$RUN_PARAM"

        # Export the HEART_COMMAND
        HEART_COMMAND="$RELEASE_ROOT_DIR/bin/$REL_NAME $CMD"
        export HEART_COMMAND

        mkdir -p "$PIPE_DIR"

        "$BINDIR/run_erl" -daemon "$PIPE_DIR" "$RUNNER_LOG_DIR" \
                          "$(_start_command)"

        _run_hooks_from_dir "$POST_START_HOOKS"
        ;;

    stop)
        _check_cookie
        _run_hooks_from_dir "$PRE_STOP_HOOKS"
        # Wait for the node to completely stop...
        PID="$(get_pid)"
        if ! nodetool "stop"; then
            exit 1
        fi
        while $(kill -s 0 "$PID" 2>/dev/null);
        do
            sleep 1
        done
        _run_hooks_from_dir "$POST_STOP_HOOKS"
        ;;

    restart)
        _check_cookie
        _run_hooks_from_dir "$PRE_CONFIGURE_HOOKS"
        _run_hooks_from_dir "$PRE_START_HOOKS"
        ## Restart the VM without exiting the process
        if ! nodetool "restart"; then
            exit 1
        fi
        ;;

    reboot)
        _check_cookie
        _run_hooks_from_dir "$PRE_CONFIGURE_HOOKS"
        _run_hooks_from_dir "$PRE_START_HOOKS"
        ## Restart the VM completely (uses heart to restart it)
        if ! nodetool "reboot"; then
            exit 1
        fi
        ;;

    pid)
        ## Get the VM's pid
        _check_cookie
        if ! get_pid; then
            exit 1
        fi
        ;;

    ping)
        _check_cookie
        ## See if the VM is alive
        if ! nodetool "ping"; then
            exit 1
        fi
        ;;

    pingpeer)
        PEERNAME=$2 nodetool "ping"
        exit_status=$?
        if [ "$exit_status" -ne 0 ]; then
            exit $exit_status
        fi
        ;;

    escript)
        _check_cookie
        ## Run an escript under the node's environment
        if ! escript $@; then
            exit 1
        fi
        ;;

    attach)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        exec "$BINDIR/to_erl" "$PIPE_DIR"
        ;;

    remote_console)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        _rem_sh
        ;;

    upgrade|downgrade|install)
        if [ -z "$2" ]; then
            echo "Missing package argument"
            echo "Usage: $REL_NAME $1 {package base name}"
            echo "NOTE {package base name} MUST NOT include the .tar.gz suffix"
            exit 1
        fi

        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        SOURCE_VERSION="$REL_VSN"
        TARGET_VERSION="$2"

        "$BINDIR/escript" "$ROOTDIR/bin/release_utils.escript" \
             "unpack_release" "$REL_NAME" "$NAME_TYPE"  "$NAME" "$COOKIE" "$TARGET_VERSION"

        # Update environment to reflect target version environment
        REL_VSN="$TARGET_VERSION"
        REL_DIR="$RELEASE_ROOT_DIR/releases/$TARGET_VERSION"

        # Prepare new configs
        _init_configs
        # We have to do some juggling to ensure the correct config is used by the upgrade handler
        # First, we detect if there was a failed upgrade, so we can start over
        if [ -f "$REL_DIR/sys.config.bak" ]; then
            mv "$REL_DIR/sys.config.bak" "$REL_DIR/sys.config"
        fi
        if [ -f "$REL_DIR/vm.args.bak" ]; then
            mv "$REL_DIR/vm.args.bak" "$REL_DIR/vm.args"
        fi
        # Then, backup the packaged configs
        cp "$REL_DIR/sys.config" "$REL_DIR/sys.config.bak"
        cp "$REL_DIR/vm.args" "$REL_DIR/vm.args.bak"
        # Then, substitute in the prepared configs
        cp "$SYS_CONFIG_PATH" "$REL_DIR/sys.config"
        cp "$VMARGS_PATH" "$REL_DIR/vm.args"
        # Make sure any pre-configuration hooks are run
        _run_hooks_from_dir "$PRE_CONFIGURE_HOOKS"
        # Run any pre-upgrade tasks
        _run_hooks_from_dir "$PRE_UPGRADE_HOOKS"

        "$BINDIR/escript" "$ROOTDIR/bin/release_utils.escript" \
             "install_release" "$REL_NAME" "$NAME_TYPE"  "$NAME" "$COOKIE" "$TARGET_VERSION"

        # We were successful, clean up the configs
        mv "$REL_DIR/sys.config.bak" "$REL_DIR/sys.config"
        mv "$REL_DIR/vm.args.bak" "$REL_DIR/vm.args"

        # Run any post-upgrade hooks
        _run_hooks_from_dir "$POST_UPGRADE_HOOKS"

        ;;
    unpack)
        if [ -z "$2" ]; then
            echo "Missing package argument"
            echo "Usage: $REL_NAME $1 {package base name}"
            echo "NOTE {package base name} MUST NOT include the .tar.gz suffix"
            exit 1
        fi

        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        exec "$BINDIR/escript" "$ROOTDIR/bin/release_utils.escript" \
             "unpack_release" "$REL_NAME" "$NAME_TYPE" "$NAME" "$COOKIE" "$2"
        ;;

    console|console_clean|console_boot)
        # .boot file typically just $REL_NAME (ie, the app name)
        # however, for debugging, sometimes start_clean.boot is useful.
        # For e.g. 'setup', one may even want to name another boot script.
        case "$1" in
            console)
                if [ -f "$REL_DIR/$REL_NAME.boot" ]; then
                  BOOTFILE="$REL_DIR/$REL_NAME"
                else
                  BOOTFILE="$REL_DIR/start"
                fi
                ;;
            console_clean)
                BOOTFILE="$ROOTDIR/bin/start_clean"
                __code_paths=$(_get_code_paths)
                EXTRA_CODE_PATHS=${__code_paths}
                ;;
            console_boot)
                shift
                BOOTFILE="$1"
                shift
                ;;
        esac
        # Setup beam-required vars
        EMU="beam"
        PROGNAME="${0#*/}"

        export EMU
        export PROGNAME

        # Store passed arguments since they will be erased by `set`
        ARGS="$@"

        _check_cookie

        # Start the VM, executing pre_start hook along
        # the way. We can't run the post_start hook because
        # the console will crash with no TTY attached
        _run_hooks_from_dir "$PRE_CONFIGURE_HOOKS"
        _run_hooks_from_dir "$PRE_START_HOOKS"

        # Build an array of arguments to pass to exec later on
        # Build it here because this command will be used for logging.
        set -- "$BINDIR/erlexec" \
            -boot "$BOOTFILE" \
            -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -env ERL_LIBS "$REL_LIB_DIR" \
            -pa "$CONSOLIDATED_DIR" \
            ${EXTRA_CODE_PATHS} \
            -args_file "$VMARGS_PATH" \
            -config "$SYS_CONFIG_PATH" \
            -mode "$CODE_LOADING_MODE" \
            ${ERL_OPTS} \
            -user Elixir.IEx.CLI \
            -extra --no-halt +iex

        # Dump environment info for logging purposes
        if [ ! -z $VERBOSE ]; then
            echo "Exec: $@" -- ${1+$ARGS} ${EXTRA_OPTS}
            echo "Root: $ROOTDIR"

            # Log the startup
            echo "$RELEASE_ROOT_DIR"
        fi;

        logger -t "$REL_NAME[$$]" "Starting up"

        exec "$@" -- ${1+$ARGS} ${EXTRA_OPTS}
        ;;

    foreground)
        # start up the release in the foreground for use by runit
        # or other supervision services

        [ -f "$REL_DIR/$REL_NAME.boot" ] && BOOTFILE="$REL_NAME" || BOOTFILE=start
        FOREGROUNDOPTIONS="-noshell -noinput +Bd"

        # Setup beam-required vars
        EMU=beam
        PROGNAME="${0#*/}"

        export EMU
        export PROGNAME

        # Store passed arguments since they will be erased by `set`
        ARGS="$@"

        _check_cookie

        # Start the VM, executing pre and post start hooks
        _run_hooks_from_dir "$PRE_CONFIGURE_HOOKS"
        _run_hooks_from_dir "$PRE_START_HOOKS"

        # Build an array of arguments to pass to exec later on
        # Build it here because this command will be used for logging.
        set -- "$BINDIR/erlexec" $FOREGROUNDOPTIONS \
            -boot "$REL_DIR/$BOOTFILE" \
            -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -env ERL_LIBS "$REL_LIB_DIR" \
            -pa "$CONSOLIDATED_DIR" \
            -args_file "$VMARGS_PATH" \
            -config "$SYS_CONFIG_PATH" \
            -mode "$CODE_LOADING_MODE" \
            ${ERL_OPTS} \
            -extra ${EXTRA_OPTS}

        # Dump environment info for logging purposes
        if [ ! -z $VERBOSE ]; then
            echo "Exec: $@" -- ${1+$ARGS}
            echo "Root: $ROOTDIR"
        fi;

        "$@" -- ${1+$ARGS} &
        __bg_pid=$!
        _run_hooks_from_dir "$POST_START_HOOKS"
        wait $__bg_pid
        ;;
    rpc)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift

        nodetool rpc $@
        ;;
    rpcterms)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift

        nodetool rpcterms $@
        ;;
    eval)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        nodetool "eval" $@
        ;;
    command)
        # Execute as command-line utility
        #
        # Like the escript command, this does not start the OTP application.
        # If your command depends on a running OTP application,
        # use
        #
        #     {:ok, _} = Application.ensure_all_started(:your_app)

        _check_cookie

        shift
        MODULE="$1"; shift
        FUNCTION="$1"; shift

        # Save extra arguments
        ARGS="$@"

        # Build arguments for erlexec
        __code_paths=$(_get_code_paths)
        set -- "$ERL_OPTS"
        [ "$SYS_CONFIG_PATH" ] && set -- "$@" -config "$SYS_CONFIG_PATH"
        set -- "$@" -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR"
        set -- "$@" -noshell
        set -- "$@" -boot start_clean
        set -- "$@" -pa "$CONSOLIDATED_DIR"
        set -- "$@" ${__code_paths}
        set -- "$@" -s "$MODULE" "$FUNCTION"

        $BINDIR/erlexec $@ -extra $ARGS
        exit "$?"
        ;;
    reload_config)
        # Reload the running system's configuration
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        _run_hooks_from_dir "$PRE_CONFIGURE_HOOKS"

        shift
        nodetool "reload_config" "$SYS_CONFIG_PATH"
        ;;
    describe)
        ## Print a summary of information about this release
        echo "$REL_NAME-$REL_VSN\n"
        echo "erts:       $ERTS_VSN"
        echo "path:       $REL_DIR"
        echo "sys.config: $SYS_CONFIG_PATH"
        echo "vm.args:    $VMARGS_PATH"
        echo "name:       $NAME"
        echo "cookie:     $COOKIE"
        echo "erl_opts:   ${ERL_OPTS:-none provided}"
        echo ""
        echo "hooks:"
        __has_hooks=0
        for hook in "$REL_DIR"/hooks/*.d/[0-9a-zA-Z]*.sh; do
            [ -f "$hook" ] || continue
            __has_hooks=1
            echo "$hook"
        done
        if [ $__has_hooks -eq 0 ]; then
            echo "No custom hooks found."
        fi
        echo ""
        echo "commands:"
        __has_commands=0
        for command in "$REL_DIR"/commands/*.sh; do
            [ -f "$command" ] || continue
            __has_commands=1
            echo "$command"
        done
        if [ $__has_commands -eq 0 ]; then
            echo "No custom commands found."
        fi
        exit 0
        ;;
    *)
        __command_path="$REL_DIR/commands/$1"
        if [ -f "$__command_path" ]; then
            _check_cookie
            . "$__command_path"
        else
            echo "Usage: $REL_NAME <task>"
            echo
            echo "Service Control"
            echo "======================="
            echo "start                          # start $REL_NAME as a daemon"
            echo "start_boot <file>              # start $REL_NAME as a daemon, but supply a custom .boot file"
            echo "foreground                     # start $REL_NAME in the foreground"
            echo "console                        # start $REL_NAME with a console attached"
            echo "console_clean                  # start a console with code paths set but no apps loaded/started"
            echo "console_boot <file>            # start $REL_NAME with a console attached, but supply a custom .boot file"
            echo "stop                           # stop the $REL_NAME daemon"
            echo "restart                        # restart the $REL_NAME daemon without shutting down the VM"
            echo "reboot                         # restart the $REL_NAME daemon"
            echo "reload_config                  # reload the current system's configuration from disk"
            echo
            echo "Upgrades"
            echo "======================="
            echo "upgrade <version>              # upgrade $REL_NAME to <version>"
            echo "downgrade <version>            # downgrade $REL_NAME to <version>"
            echo "install <version>              # install the $REL_NAME-<version> release, but do not upgrade to it"
            echo
            echo "Utilities"
            echo "======================="
            echo "attach                         # attach the current TTY to $REL_NAME's console"
            echo "remote_console                 # remote shell to $REL_NAME's console"
            echo "pid                            # get the pid of the running $REL_NAME instance"
            echo "ping                           # checks if $REL_NAME is running, pong is returned if successful"
            echo "pingpeer <peer>                # check if a peer node is running, pong is returned if successful"
            echo "escript <file>                 # execute an escript"
            echo "rpc <mod> <fun> [<args..>]     # execute an RPC call using the given MFA"
            echo "rpcterms <mod> <fun> [<expr>]  # execute an RPC call using the given Erlang expression for args"
            echo "eval <expr>                    # execute the given Erlang expression on the running node"
            echo "command <mod> <fun> [<args..>] # execute the given MFA"
            echo "describe                       # print useful information about the $REL_NAME release"
            echo
            echo "Custom Commands"
            echo "======================="
            __has_commands=0
            for command in "$REL_DIR"/commands/*.sh; do
                [ -f "$command" ] || continue
                __has_commands=1
                echo "$command"
            done
            if [ $__has_commands -eq 0 ]; then
                echo "No custom commands found."
            fi
            echo ""
            exit 1
        fi
        ;;
esac

exit 0

#!/bin/sh

set -e

# Set VERBOSE to enable verbose logging of the boot script
#VERBOSE=true
if [ ! -z $DEBUG_BOOT ]; then
    set -x
fi;

my_readlink_f() {
    TARGET_FILE="$1"
    cd $(dirname "$TARGET_FILE")
    TARGET_FILE=$(basename "$TARGET_FILE")

    # Iterate down a (possible) chain of symlinks
    while [ -L "$TARGET_FILE" ]
    do
        TARGET_FILE=$(readlink "$TARGET_FILE")
        cd $(dirname "$TARGET_FILE")
        TARGET_FILE=$(basename "$TARGET_FILE")
    done
    # Compute the canonicalized name by finding the physical path
    # for the directory we're in and appending the target file.
    PHYS_DIR=$(pwd -P)
    RESULT="$PHYS_DIR/$TARGET_FILE"
    echo "$RESULT"
}

# Path to this script
if uname | grep -q 'Darwin'; then
  # on OSX, best to install coreutils from homebrew or similar
  # to get greadlink
  if command -v greadlink >/dev/null 2>&1; then
    SCRIPT="${SCRIPT:-$(greadlink -f "$0")}"
  else
    SCRIPT="${SCRIPT:-$(my_readlink_f "$0")}"
  fi
else
  SCRIPT="${SCRIPT:-$(readlink -f "$0" )}"
fi

# Parent directory of this script
SCRIPT_DIR="${SCRIPT_DIR:-$(dirname "${SCRIPT}")}"
# Root directory of all releases
RELEASE_ROOT_DIR="${RELEASE_ROOT_DIR:-$(dirname $(dirname ${SCRIPT_DIR}))}"

# Disable flow control for run_erl
# Flow control can cause several problems. On Linux, if you
# accidentally hit Ctrl-S (instead of Ctrl-D to detach) and
# then some other key, the entire beam process will hang when
# attempting to write to stdout. On Solaris, the beam process
# will hang on writing if ScrollLock is on.
RUN_ERL_DISABLE_FLOWCNTRL="${RUN_ERL_DISABLE_FLOWCNTRL:-true}"
# Name of the release
REL_NAME="${REL_NAME:-<%= release_name %>}"
# Current version of the release
REL_VSN="${REL_VSN:-<%= release_version %>}"
# Current version of ERTS being used
# If this is not present/unset, it will be detected
<%= if ((is_binary(include_erts) or include_erts) and not is_nil(erts_vsn)) do %>ERTS_VSN="${ERTS_VSN:-<%= erts_vsn %>}"<% end %>
# VM code loading mode, embedded by default, can also be interactive
# See http://erlang.org/doc/man/code.html
CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}"
# Path to start_erl.data
START_ERL_DATA="${START_ERL_DATA:-$RELEASE_ROOT_DIR/releases/start_erl.data}"
# Directory containing the current version of this release
REL_DIR="${REL_DIR:-$RELEASE_ROOT_DIR/releases/$REL_VSN}"
# The lib directory for this release
REL_LIB_DIR="${REL_LIB_DIR:-$RELEASE_ROOT_DIR/lib}"
# Options passed to erl
ERL_OPTS="${ERL_OPTS:-<%= release.profile.erl_opts %>}"
# When stdout is piped to a file, this is the directory those files will
# be stored in. defaults to /log in the release root directory

# RELEASE_MUTABLE_DIR
RELEASE_MUTABLE_DIR="${RELEASE_MUTABLE_DIR:-$RELEASE_ROOT_DIR/var}"

RUNNER_LOG_DIR="${RUNNER_LOG_DIR:-$RELEASE_MUTABLE_DIR/log}"
# A string of extra options to pass to erl, here for plugins
EXTRA_OPTS="${EXTRA_OPTS:-}"

# Pre-start/stop event hook paths
PRE_CONFIGURE_HOOKS="$REL_DIR/hooks/pre_configure.d"
PRE_START_HOOKS="$REL_DIR/hooks/pre_start.d"
POST_START_HOOKS="$REL_DIR/hooks/post_start.d"
PRE_STOP_HOOKS="$REL_DIR/hooks/pre_stop.d"
POST_STOP_HOOKS="$REL_DIR/hooks/post_stop.d"
PRE_UPGRADE_HOOKS="$REL_DIR/hooks/pre_upgrade.d"
POST_UPGRADE_HOOKS="$REL_DIR/hooks/post_upgrade.d"

# Get node pid
get_pid() {
    if output="$(nodetool rpcterms os getpid)"
    then
        echo "$output" | sed -e 's/"//g'
        return 0
    else
        echo "$output"
        return 1
    fi
}

# Generate a unique nodename
gen_nodename() {
    id="longname$(gen_id)-${NAME}"
    "$BINDIR/erl" -boot start_clean -eval '[Host] = tl(string:tokens(atom_to_list(node()),"@")), io:format("~s~n", [Host]), halt()' -noshell ${NAME_TYPE} $id
}

# Generate a random id
gen_id() {
    od -t x -N 4 /dev/urandom | head -n1 | awk '{print $2}'
}

# Control a node
# Use like `nodetool "ping"`
nodetool() {
    command="$1"; shift
    name=${PEERNAME:-$NAME}
    "$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$name" \
                            -setcookie "$COOKIE" "$command" $@
}

# Run an escript in the node's environment
# Use like `escript "path/to/escript"`
escript() {
    shift; scriptpath="$1"; shift
    export RELEASE_ROOT_DIR

    "$ERTS_DIR/bin/escript" "$ROOTDIR/$scriptpath" $@
}

# Private. Load target cookie, either from vm.args or $HOME/.cookie
_load_cookie() {
    COOKIE_ARG="$(grep '^-setcookie' "$VMARGS_PATH" || true)"
    DEFAULT_COOKIE_FILE="$HOME/.erlang.cookie"
    if [ -z "$COOKIE_ARG" ]; then
        if [ -f "$DEFAULT_COOKIE_FILE" ]; then
            COOKIE="$(cat "$DEFAULT_COOKIE_FILE")"
        fi
    else
        # Extract cookie name from COOKIE_ARG
        COOKIE="$(echo "$COOKIE_ARG" | awk '{print $2}')"
    fi
}

# Private. Ensure that cookie is set.
_check_cookie() {
    # Attempt reloading cookie in case it has been set in a hook
    if [ -z "$COOKIE" ]; then
        _load_cookie
    fi
    # Die if cookie is still not set, as connecting via distribution will fail
    if [ -z "$COOKIE" ]; then
        printf "a secret cookie must be provided in one of the following ways:\n  - with vm.args using the -setcookie parameter,\n  or\n  by writing the cookie to '$DEFAULT_COOKIE_FILE', with permissions set to 0400"
        exit 1
    fi
}

# Private. For setting up the Erlang runtime to use
_init_erts_config() {
    if [ -z "$ERTS_VSN" ]; then
        set +e # temporarily disable so we can display a nice error message to the user
        __erl="$(which erl)"
        set -e
        if [ -z "${__erl}"  ]; then
            echo 'erlang runtime not found. If erlang is installed check your $PATH. aborting.'
            exit 1
        fi
        export ROOTDIR="$("$__erl" -boot start_clean -eval 'io:format("~s~n", [code:root_dir()]), halt().' -noshell)"
        export ERTS_VSN="$(_get_erts_vsn)"
        export ERTS_DIR="$ROOTDIR"/"erts-$ERTS_VSN"
    else
        __erts_dir="$RELEASE_ROOT_DIR/erts-$ERTS_VSN"
        if [ -d "$__erts_dir" ]; then
            export ROOTDIR="$RELEASE_ROOT_DIR"
            export ERTS_DIR="$__erts_dir"
        else
            unset ERTS_VSN
            _init_erts_config
        fi
    fi
}

# Private. For determining the version of ERTS available to the release
# This is only ever called if ERTS_VSN is not set
_get_erts_vsn() {
    if [ -z "$ERTS_VSN" ]; then
        "$ROOTDIR"/bin/erl \
            -boot start_clean \
            -eval 'Ver = erlang:system_info(version), io:format("~s~n", [Ver]), halt()' \
            -noshell
    else
        echo "$ERTS_VSN"
    fi
}

# Private. Gets a list of code paths for this release
_get_code_paths() {
    "$ERTS_DIR/bin/escript" "$ROOTDIR/bin/release_utils.escript" "get_code_paths" "$ROOTDIR" "$ERTS_DIR" "$REL_NAME" "$REL_VSN"
}

# Private. Open a shell on a remote node
_rem_sh() {
    # Generate a unique id used to allow multiple remsh to the same node
    # transparently
    id="remsh$(gen_id)-${NAME}"

    # Get the node's ticktime so that we use the same thing.
    TICKTIME="$(nodetool rpcterms net_kernel get_net_ticktime)"

    # Setup remote shell command to control node
    if [ ! -z "$USE_ERL_SHELL" ]; then
        exec "$BINDIR/erl" \
            -hidden \
            -boot start_clean -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -kernel net_ticktime $TICKTIME \
            "$NAME_TYPE" "$id" -remsh "$NAME" -setcookie "$COOKIE"
    else
        __code_paths=$(_get_code_paths)
        exec "$BINDIR/erl" \
            -pa "$CONSOLIDATED_DIR" \
            ${__code_paths} \
            -hidden -noshell \
            -boot start_clean -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -kernel net_ticktime $TICKTIME \
            -user Elixir.IEx.CLI "$NAME_TYPE" "$id" -setcookie "$COOKIE" \
            -extra --no-halt +iex -"$NAME_TYPE" "$id" --cookie "$COOKIE" --remsh "$NAME"
    fi
}

# Output a start command for the last argument of run_erl
_start_command() {
    printf "exec \"%s\" \"%s\" -- %s %s" "$RELEASE_ROOT_DIR/bin/$REL_NAME" \
           "$START_OPTION" "${ARGS}" "${EXTRA_OPTS}"
}

# Do a textual replacement of ${VAR} occurrences in $1 and pipe to $2
_replace_os_vars() {
    awk '
        function escape(s) {
            gsub(/'\&'/, "\\\\&", s);
            return s;
        }
        {
            while(match($0,"[$]{[^}]*}")) {
                var=substr($0,RSTART+2,RLENGTH-3);
                gsub("[$]{"var"}", escape(ENVIRON[var]))
            }
        }1' < "$1" > "$1.bak"
    mv -- "$1.bak" "$1"
}

# Private. Run hooks from directory.
_run_hooks_from_dir() {
   if [ -d "$1" ]; then
      for file in $1/[0-9a-zA-Z]*.sh; do
        [ -f "$file" ] || continue
        . "$file"
      done
   fi
}

# Private. Sets config paths for sys.config and vm.args,
# and ensures that env var replacements are performed
_init_configs() {
    # Set VMARGS_PATH, the path to the vm.args file to use
    # Use $RELEASE_CONFIG_DIR/vm.args if exists, otherwise releases/VSN/vm.args
    if [ -z "$VMARGS_PATH" ]; then
        if [ -f "$RELEASE_CONFIG_DIR/vm.args" ]; then
            export VMARGS_PATH="$RELEASE_CONFIG_DIR/vm.args"
        else
            export VMARGS_PATH="$REL_DIR/vm.args"
        fi
        export SRC_VMARGS_PATH="$VMARGS_PATH"
    else
        if [ "$VMARGS_PATH" != "$RELEASE_MUTABLE_DIR/vm.args" ]; then
            export SRC_VMARGS_PATH="$VMARGS_PATH"
        else
            if [ -f "$RELEASE_CONFIG_DIR/vm.args" ]; then
                export VMARGS_PATH="$RELEASE_CONFIG_DIR/vm.args"
            else
                export VMARGS_PATH="$REL_DIR/vm.args"
            fi
            export SRC_VMARGS_PATH="$VMARGS_PATH"
        fi
    fi
    if [ "$SRC_VMARGS_PATH" != "$RELEASE_MUTABLE_DIR/vm.args" ]; then
        echo "#### Generated - edit/create $RELEASE_CONFIG_DIR/vm.args instead." \
            >  "$RELEASE_MUTABLE_DIR/vm.args"
        cat  "$SRC_VMARGS_PATH"                              \
            >> "$RELEASE_MUTABLE_DIR/vm.args"
        export VMARGS_PATH="$RELEASE_MUTABLE_DIR"/vm.args
    fi
    if [ $REPLACE_OS_VARS ]; then
        _replace_os_vars "$VMARGS_PATH"
    fi

    # Set SYS_CONFIG_PATH, the path to the sys.config file to use
    # Use $RELEASE_CONFIG_DIR/sys.config if exists, otherwise releases/VSN/sys.config
    if [ -z "$SYS_CONFIG_PATH" ]; then
        if [ -f "$RELEASE_CONFIG_DIR/sys.config" ]; then
            export SYS_CONFIG_PATH="$RELEASE_CONFIG_DIR/sys.config"
        else
            export SYS_CONFIG_PATH="$REL_DIR/sys.config"
        fi
        export SRC_SYS_CONFIG_PATH="$SYS_CONFIG_PATH"
    else
        if [ "$SYS_CONFIG_PATH" != "$RELEASE_MUTABLE_DIR/sys.config" ]; then
            export SRC_SYS_CONFIG_PATH="$SYS_CONFIG_PATH"
        else
            if [ -f "$RELEASE_CONFIG_DIR/sys.config" ]; then
                export SYS_CONFIG_PATH="$RELEASE_CONFIG_DIR/sys.config"
            else
                export SYS_CONFIG_PATH="$REL_DIR/sys.config"
            fi
            export SRC_SYS_CONFIG_PATH="$SYS_CONFIG_PATH"
        fi
    fi
    if [ "$SRC_SYS_CONFIG_PATH" != "$RELEASE_MUTABLE_DIR/sys.config" ]; then
        (echo "%% Generated - edit/create $RELEASE_CONFIG_DIR/sys.config instead."; \
        cat  "$SRC_SYS_CONFIG_PATH")                              \
            > "$RELEASE_MUTABLE_DIR/sys.config"
        export SYS_CONFIG_PATH="$RELEASE_MUTABLE_DIR"/sys.config
    fi
    if [ $REPLACE_OS_VARS ]; then
        _replace_os_vars "$SYS_CONFIG_PATH"
    fi
}

# If TERM is not set, set it to xterm
if [ -z "$TERM" ]; then
    export TERM=xterm
fi

# Make sure ERTS configuration is set
_init_erts_config
echo "$ERTS_VSN $REL_VSN" > "$START_ERL_DATA"

# Allow override of where to read configuration from
# By default it's RELEASE_ROOT_DIR
if [ -z "$RELEASE_CONFIG_DIR" ]; then
    export RELEASE_CONFIG_DIR="$RELEASE_ROOT_DIR"
fi

# Make sure directories exist
mkdir -p "$RELEASE_MUTABLE_DIR"
echo "Files in this directory are regenerated frequently, edits will be lost" \
    > "$RELEASE_MUTABLE_DIR/WARNING_README"
mkdir -p "$RUNNER_LOG_DIR"

# Make sure config paths are setup
_init_configs

# Extract the target node name from node.args
# Should be `-sname somename` or `-name somename@somehost`
export NAME_ARG="$(egrep '^-s?name' "$VMARGS_PATH" || true)"
if [ -z "$NAME_ARG" ]; then
    echo "vm.args needs to have either -name or -sname parameter."
    exit 1
fi

# Extract the name type and name from the NAME_ARG for REMSH
# NAME_TYPE should be -name or -sname
export NAME_TYPE="$(echo "$NAME_ARG" | awk '{print $1}')"
# NAME will be either `somename` or `somename@somehost`
export NAME="$(echo "$NAME_ARG" | awk '{print $2}')"

# Where the pipe will be stored when using `start`
# This is used so you can attach the running application to the current
# shell using `attach`
PIPE_DIR="${PIPE_DIR:-$RELEASE_MUTABLE_DIR/erl_pipes/$NAME/}"

# Extract the target cookie
_load_cookie

export ROOTDIR="$RELEASE_ROOT_DIR"
export BINDIR="$ERTS_DIR/bin"
export EMU="beam"
export PROGNAME="erl"
export LD_LIBRARY_PATH="$ERTS_DIR/lib:$LD_LIBRARY_PATH"
export ERTS_LIB_DIR="$ERTS_DIR/../lib"
CONSOLIDATED_DIR="$ROOTDIR/lib/${REL_NAME}-${REL_VSN}/consolidated"

cd "$ROOTDIR"

# User can specify an sname without @hostname
# This will fail when creating remote shell
# So here we check for @ and add @hostname if missing
case $NAME in
    *@*)
        # Nothing to do
        ;;
    *)
        NAME=$NAME@$(gen_nodename)
        ;;
esac

# For Elixir runtime
export DISTILLERY_TASK="$1"

# Check the first argument for instructions
case "$1" in
    start|start_boot)

        # Make sure there is not already a node running
        #RES=`$NODETOOL ping`
        #if [ "$RES" = "pong" ]; then
        #    echo "Node is already running!"
        #    exit 1
        #fi
        # Save this for later.
        CMD=$1
        case "$1" in
            start)
                shift
                START_OPTION="console"
                HEART_OPTION="start"
                ;;
            start_boot)
                shift
                START_OPTION="console_boot"
                HEART_OPTION="start_boot"
                ;;
        esac
        ARGS="$@"
        RUN_PARAM="$@"

        _check_cookie
        _run_hooks_from_dir "$PRE_CONFIGURE_HOOKS"
        _run_hooks_from_dir "$PRE_START_HOOKS"

        # Set arguments for the heart command
        set -- "$SCRIPT_DIR/$REL_NAME" "$HEART_OPTION"
        [ "$RUN_PARAM" ] && set -- "$@" "$RUN_PARAM"

        # Export the HEART_COMMAND
        HEART_COMMAND="$RELEASE_ROOT_DIR/bin/$REL_NAME $CMD"
        export HEART_COMMAND

        mkdir -p "$PIPE_DIR"

        "$BINDIR/run_erl" -daemon "$PIPE_DIR" "$RUNNER_LOG_DIR" \
                          "$(_start_command)"

        _run_hooks_from_dir "$POST_START_HOOKS"
        ;;

    stop)
        _check_cookie
        _run_hooks_from_dir "$PRE_STOP_HOOKS"
        # Wait for the node to completely stop...
        PID="$(get_pid)"
        if ! nodetool "stop"; then
            exit 1
        fi
        while $(kill -s 0 "$PID" 2>/dev/null);
        do
            sleep 1
        done
        _run_hooks_from_dir "$POST_STOP_HOOKS"
        ;;

    restart)
        _check_cookie
        _run_hooks_from_dir "$PRE_CONFIGURE_HOOKS"
        _run_hooks_from_dir "$PRE_START_HOOKS"
        ## Restart the VM without exiting the process
        if ! nodetool "restart"; then
            exit 1
        fi
        ;;

    reboot)
        _check_cookie
        _run_hooks_from_dir "$PRE_CONFIGURE_HOOKS"
        _run_hooks_from_dir "$PRE_START_HOOKS"
        ## Restart the VM completely (uses heart to restart it)
        if ! nodetool "reboot"; then
            exit 1
        fi
        ;;

    pid)
        ## Get the VM's pid
        _check_cookie
        if ! get_pid; then
            exit 1
        fi
        ;;

    ping)
        _check_cookie
        ## See if the VM is alive
        if ! nodetool "ping"; then
            exit 1
        fi
        ;;

    pingpeer)
        PEERNAME=$2 nodetool "ping"
        exit_status=$?
        if [ "$exit_status" -ne 0 ]; then
            exit $exit_status
        fi
        ;;

    escript)
        _check_cookie
        ## Run an escript under the node's environment
        if ! escript $@; then
            exit 1
        fi
        ;;

    attach)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        exec "$BINDIR/to_erl" "$PIPE_DIR"
        ;;

    remote_console)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        _rem_sh
        ;;

    upgrade|downgrade|install)
        if [ -z "$2" ]; then
            echo "Missing package argument"
            echo "Usage: $REL_NAME $1 {package base name}"
            echo "NOTE {package base name} MUST NOT include the .tar.gz suffix"
            exit 1
        fi

        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        SOURCE_VERSION="$REL_VSN"
        TARGET_VERSION="$2"

        "$BINDIR/escript" "$ROOTDIR/bin/release_utils.escript" \
             "unpack_release" "$REL_NAME" "$NAME_TYPE"  "$NAME" "$COOKIE" "$TARGET_VERSION"

        # Update environment to reflect target version environment
        REL_VSN="$TARGET_VERSION"
        REL_DIR="$RELEASE_ROOT_DIR/releases/$TARGET_VERSION"

        # Prepare new configs
        _init_configs
        # We have to do some juggling to ensure the correct config is used by the upgrade handler
        # First, we detect if there was a failed upgrade, so we can start over
        if [ -f "$REL_DIR/sys.config.bak" ]; then
            mv "$REL_DIR/sys.config.bak" "$REL_DIR/sys.config"
        fi
        if [ -f "$REL_DIR/vm.args.bak" ]; then
            mv "$REL_DIR/vm.args.bak" "$REL_DIR/vm.args"
        fi
        # Then, backup the packaged configs
        cp "$REL_DIR/sys.config" "$REL_DIR/sys.config.bak"
        cp "$REL_DIR/vm.args" "$REL_DIR/vm.args.bak"
        # Then, substitute in the prepared configs
        cp "$SYS_CONFIG_PATH" "$REL_DIR/sys.config"
        cp "$VMARGS_PATH" "$REL_DIR/vm.args"
        # Make sure any pre-configuration hooks are run
        _run_hooks_from_dir "$PRE_CONFIGURE_HOOKS"
        # Run any pre-upgrade tasks
        _run_hooks_from_dir "$PRE_UPGRADE_HOOKS"

        "$BINDIR/escript" "$ROOTDIR/bin/release_utils.escript" \
             "install_release" "$REL_NAME" "$NAME_TYPE"  "$NAME" "$COOKIE" "$TARGET_VERSION"

        # We were successful, clean up the configs
        mv "$REL_DIR/sys.config.bak" "$REL_DIR/sys.config"
        mv "$REL_DIR/vm.args.bak" "$REL_DIR/vm.args"

        # Run any post-upgrade hooks
        _run_hooks_from_dir "$POST_UPGRADE_HOOKS"

        ;;
    unpack)
        if [ -z "$2" ]; then
            echo "Missing package argument"
            echo "Usage: $REL_NAME $1 {package base name}"
            echo "NOTE {package base name} MUST NOT include the .tar.gz suffix"
            exit 1
        fi

        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        exec "$BINDIR/escript" "$ROOTDIR/bin/release_utils.escript" \
             "unpack_release" "$REL_NAME" "$NAME_TYPE" "$NAME" "$COOKIE" "$2"
        ;;

    console|console_clean|console_boot)
        # .boot file typically just $REL_NAME (ie, the app name)
        # however, for debugging, sometimes start_clean.boot is useful.
        # For e.g. 'setup', one may even want to name another boot script.
        case "$1" in
            console)
                if [ -f "$REL_DIR/$REL_NAME.boot" ]; then
                  BOOTFILE="$REL_DIR/$REL_NAME"
                else
                  BOOTFILE="$REL_DIR/start"
                fi
                ;;
            console_clean)
                BOOTFILE="$ROOTDIR/bin/start_clean"
                __code_paths=$(_get_code_paths)
                EXTRA_CODE_PATHS=${__code_paths}
                ;;
            console_boot)
                shift
                BOOTFILE="$1"
                shift
                ;;
        esac
        # Setup beam-required vars
        EMU="beam"
        PROGNAME="${0#*/}"

        export EMU
        export PROGNAME

        # Store passed arguments since they will be erased by `set`
        ARGS="$@"

        _check_cookie

        # Start the VM, executing pre_start hook along
        # the way. We can't run the post_start hook because
        # the console will crash with no TTY attached
        _run_hooks_from_dir "$PRE_CONFIGURE_HOOKS"
        _run_hooks_from_dir "$PRE_START_HOOKS"

        # Build an array of arguments to pass to exec later on
        # Build it here because this command will be used for logging.
        set -- "$BINDIR/erlexec" \
            -boot "$BOOTFILE" \
            -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -env ERL_LIBS "$REL_LIB_DIR" \
            -pa "$CONSOLIDATED_DIR" \
            ${EXTRA_CODE_PATHS} \
            -args_file "$VMARGS_PATH" \
            -config "$SYS_CONFIG_PATH" \
            -mode "$CODE_LOADING_MODE" \
            ${ERL_OPTS} \
            -user Elixir.IEx.CLI \
            -extra --no-halt +iex

        # Dump environment info for logging purposes
        if [ ! -z $VERBOSE ]; then
            echo "Exec: $@" -- ${1+$ARGS} ${EXTRA_OPTS}
            echo "Root: $ROOTDIR"

            # Log the startup
            echo "$RELEASE_ROOT_DIR"
        fi;

        logger -t "$REL_NAME[$$]" "Starting up"

        exec "$@" -- ${1+$ARGS} ${EXTRA_OPTS}
        ;;

    foreground)
        # start up the release in the foreground for use by runit
        # or other supervision services

        [ -f "$REL_DIR/$REL_NAME.boot" ] && BOOTFILE="$REL_NAME" || BOOTFILE=start
        FOREGROUNDOPTIONS="-noshell -noinput +Bd"

        # Setup beam-required vars
        EMU=beam
        PROGNAME="${0#*/}"

        export EMU
        export PROGNAME

        # Store passed arguments since they will be erased by `set`
        ARGS="$@"

        _check_cookie

        # Start the VM, executing pre and post start hooks
        _run_hooks_from_dir "$PRE_CONFIGURE_HOOKS"
        _run_hooks_from_dir "$PRE_START_HOOKS"

        # Build an array of arguments to pass to exec later on
        # Build it here because this command will be used for logging.
        set -- "$BINDIR/erlexec" $FOREGROUNDOPTIONS \
            -boot "$REL_DIR/$BOOTFILE" \
            -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
            -env ERL_LIBS "$REL_LIB_DIR" \
            -pa "$CONSOLIDATED_DIR" \
            -args_file "$VMARGS_PATH" \
            -config "$SYS_CONFIG_PATH" \
            -mode "$CODE_LOADING_MODE" \
            ${ERL_OPTS} \
            -extra ${EXTRA_OPTS}

        # Dump environment info for logging purposes
        if [ ! -z $VERBOSE ]; then
            echo "Exec: $@" -- ${1+$ARGS}
            echo "Root: $ROOTDIR"
        fi;

        "$@" -- ${1+$ARGS} &
        __bg_pid=$!
        _run_hooks_from_dir "$POST_START_HOOKS"
        wait $__bg_pid
        ;;
    rpc)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift

        nodetool rpc $@
        ;;
    rpcterms)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift

        nodetool rpcterms $@
        ;;
    eval)
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift
        nodetool "eval" $@
        ;;
    command)
        # Execute as command-line utility
        #
        # Like the escript command, this does not start the OTP application.
        # If your command depends on a running OTP application,
        # use
        #
        #     {:ok, _} = Application.ensure_all_started(:your_app)

        _check_cookie

        shift
        MODULE="$1"; shift
        FUNCTION="$1"; shift

        # Save extra arguments
        ARGS="$@"

        # Build arguments for erlexec
        __code_paths=$(_get_code_paths)
        set -- "$ERL_OPTS"
        [ "$SYS_CONFIG_PATH" ] && set -- "$@" -config "$SYS_CONFIG_PATH"
        set -- "$@" -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR"
        set -- "$@" -noshell
        set -- "$@" -boot start_clean
        set -- "$@" -pa "$CONSOLIDATED_DIR"
        set -- "$@" ${__code_paths}
        set -- "$@" -s "$MODULE" "$FUNCTION"

        $BINDIR/erlexec $@ -extra $ARGS
        exit "$?"
        ;;
    reload_config)
        # Reload the running system's configuration
        _check_cookie

        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        _run_hooks_from_dir "$PRE_CONFIGURE_HOOKS"

        shift
        nodetool "reload_config" "$SYS_CONFIG_PATH"
        ;;
    describe)
        ## Print a summary of information about this release
        echo "$REL_NAME-$REL_VSN\n"
        echo "erts:       $ERTS_VSN"
        echo "path:       $REL_DIR"
        echo "sys.config: $SYS_CONFIG_PATH"
        echo "vm.args:    $VMARGS_PATH"
        echo "name:       $NAME"
        echo "cookie:     $COOKIE"
        echo "erl_opts:   ${ERL_OPTS:-none provided}"
        echo ""
        echo "hooks:"
        __has_hooks=0
        for hook in "$REL_DIR"/hooks/*.d/[0-9a-zA-Z]*.sh; do
            [ -f "$hook" ] || continue
            __has_hooks=1
            echo "$hook"
        done
        if [ $__has_hooks -eq 0 ]; then
            echo "No custom hooks found."
        fi
        echo ""
        echo "commands:"
        __has_commands=0
        for command in "$REL_DIR"/commands/*.sh; do
            [ -f "$command" ] || continue
            __has_commands=1
            echo "$command"
        done
        if [ $__has_commands -eq 0 ]; then
            echo "No custom commands found."
        fi
        exit 0
        ;;
    *)
        __command_path="$REL_DIR/commands/$1"
        if [ -f "$__command_path" ]; then
            _check_cookie
            . "$__command_path"
        else
            echo "Usage: $REL_NAME <task>"
            echo
            echo "Service Control"
            echo "======================="
            echo "start                          # start $REL_NAME as a daemon"
            echo "start_boot <file>              # start $REL_NAME as a daemon, but supply a custom .boot file"
            echo "foreground                     # start $REL_NAME in the foreground"
            echo "console                        # start $REL_NAME with a console attached"
            echo "console_clean                  # start a console with code paths set but no apps loaded/started"
            echo "console_boot <file>            # start $REL_NAME with a console attached, but supply a custom .boot file"
            echo "stop                           # stop the $REL_NAME daemon"
            echo "restart                        # restart the $REL_NAME daemon without shutting down the VM"
            echo "reboot                         # restart the $REL_NAME daemon"
            echo "reload_config                  # reload the current system's configuration from disk"
            echo
            echo "Upgrades"
            echo "======================="
            echo "upgrade <version>              # upgrade $REL_NAME to <version>"
            echo "downgrade <version>            # downgrade $REL_NAME to <version>"
            echo "install <version>              # install the $REL_NAME-<version> release, but do not upgrade to it"
            echo
            echo "Utilities"
            echo "======================="
            echo "attach                         # attach the current TTY to $REL_NAME's console"
            echo "remote_console                 # remote shell to $REL_NAME's console"
            echo "pid                            # get the pid of the running $REL_NAME instance"
            echo "ping                           # checks if $REL_NAME is running, pong is returned if successful"
            echo "pingpeer <peer>                # check if a peer node is running, pong is returned if successful"
            echo "escript <file>                 # execute an escript"
            echo "rpc <mod> <fun> [<args..>]     # execute an RPC call using the given MFA"
            echo "rpcterms <mod> <fun> [<expr>]  # execute an RPC call using the given Erlang expression for args"
            echo "eval <expr>                    # execute the given Erlang expression on the running node"
            echo "command <mod> <fun> [<args..>] # execute the given MFA"
            echo "describe                       # print useful information about the $REL_NAME release"
            echo
            echo "Custom Commands"
            echo "======================="
            __has_commands=0
            for command in "$REL_DIR"/commands/*.sh; do
                [ -f "$command" ] || continue
                __has_commands=1
                echo "$command"
            done
            if [ $__has_commands -eq 0 ]; then
                echo "No custom commands found."
            fi
            echo ""
            exit 1
        fi
        ;;
esac

exit 0


business-card-link

business-card-link

      <%= @persona.name %>

Panoptikum-ID

<%= @persona.pid %>

Permalink (URI)

<%= PanWeb.Endpoint.url %>/<%= @persona.pid %>

Name

<%= @persona.name %>

          <%= if @persona.uri do %>

Uri

<%= @persona.uri %>

          <% end %>

Business Cards

<%= link [fa_icon("vcard-o"), " Show"], to: persona_frontend_url(@conn, :business_card, @persona) %>

        Id: <%= @persona.id %>

        <%= if @persona.image_url do %>
          <object data="<%= @persona.image_url %>"
                  alt="<%= @persona.image_title%>"
                  type="image/png"
                  width="150"
                  class="thumbnail"
                  id="photo">

          </object>
        <% else %>

        <% end %>

    <%= if @current_user do %>

        <%= like_or_unlike(@current_user.id, @persona.id) %>
        <%= follow_or_unfollow(@current_user.id, @persona.id) %>

    <% end %>

<%= if @persona.description || @persona.long_description do %>

<%= @persona.description %>

      <%= markdown(@persona.long_description) %>

<% end %>

<%= if @engagements != [] do %>

Engagements, <%= @persona.name %> has entered

          Podcast
          Role

        <%= for {podcast, engagements} <- Enum.group_by(@engagements, &Map.get(&1, :podcast)) do %>

             <%= link [fa_icon("podcast"), " ", truncate(podcast.title, 50)],
                           to: podcast_frontend_path(@conn, :show, podcast),
                           class: "btn btn-default btn-xs",
                           style: "color: #000" %>

              <%= for engagement <- engagements do %>
                <%= engagement.role %>
              <% end %>

        <% end %>

<% end %>

<%= if @gigs != [] do %>

Gigs, <%= @persona.name %> has been engaged in

          Date
          Podcast
          Episode
          Role

        <%= for episode <- ordered_episodes(@gigs) do %>

            <%= if episode.publishing_date, do: format_date(episode.publishing_date) %>
            <%= link [fa_icon("podcast"), " ", episode.podcast.title],
                           to: podcast_frontend_path(@conn, :show, episode.podcast),
                           class: "btn btn-default btn-xs truncate",
                           style: "color: #000" %>
            <%= link [fa_icon("headphones"), " ", episode.title],
                        to: episode_frontend_path(@conn, :show, episode),
                        class: "btn btn-primary btn-xs truncate" %>

              <%= for gig <- @grouped_gigs[episode] do %>
                <%= gig.role %>
              <% end %>

        <% end %>

<% end %>

<%= if @messages.total_entries > 0 do %>

Messages created by <%= @persona.name %>

      <%= pagination_links @conn, @messages, [Integer.to_string(@persona.id)],
                   path: &persona_frontend_path/4,
                   action: :show,
                   view_style: :bootstrap %>

        <%= for message <- @messages.entries do %>
          <li class="list-group-item message-<%= message.type %>">

              <%= if message.creator, do: message.creator.name, else: message.persona.name %>:

            <%= raw message.content %>
            <%= message.inserted_at %>

        <% end %>

<% end %>

<%= if @current_user && @current_user.podcaster == true  && @current_user.email_confirmed && @persona.email != nil do %>
  <%= link "Claim", to: persona_frontend_path(@conn, :claim, @persona),
                    class: "btn btn-normal",
                    method: :post,
                    data: [confirm: "Are you sure?"] %>

  <button class="btn btn-primary btn-sm"
          data-toggle="popover"
          data-placement="right"
          data-title="Personas"
          data-html="true"
          data-content="You can send an email to the owner of this persona and ask her for permission
                        to add you as a manifestation of this persona.

                        Your name, username and email address will be sent alongside in the email
                        to give the owner a chance to get in contact with you.">
    <%= fa_icon "info-circle" %> Help
  </button>
<% end %>

      <%= @persona.name %>

Pid

<%= @persona.pid %>

Name

<%= @persona.name %>

          <%= if @persona.uri do %>

Uri

<%= @persona.uri %>

          <% end %>

        <%= if @persona.image_url do %>
          <object data="<%= @persona.image_url %>"
                  alt="<%= @persona.image_title%>"
                  type="image/png"
                  width="150"
                  class="thumbnail"
                  id="photo">

          </object>
        <% else %>

        <% end %>

    <%= if @current_user do %>

        <%= like_or_unlike(@current_user.id, @persona.id) %>
        <%= follow_or_unfollow(@current_user.id, @persona.id) %>

    <% end %>

<%= if @persona.description || @persona.long_description do %>

<%= @persona.description %>

      <%= markdown(@persona.long_description) %>

<% end %>

<%= if @engagements != [] do %>

Engagements, <%= @persona.name %> has entered

          Podcast
          Role

        <%= for {podcast, engagements} <- Enum.group_by(@engagements, &Map.get(&1, :podcast)) do %>

             <%= link [fa_icon("podcast"), " ", truncate(podcast.title, 50)],
                           to: podcast_frontend_path(@conn, :show, podcast),
                           class: "btn btn-default btn-xs",
                           style: "color: #000" %>

              <%= for engagement <- engagements do %>
                <%= engagement.role %>
              <% end %>

        <% end %>

<% end %>

<%= if @gigs != [] do %>

Gigs, <%= @persona.name %> has been engaged in

          Date
          Podcast
          Episode
          Role

        <%= for episode <- ordered_episodes(@gigs) do %>

            <%= if episode.publishing_date, do: format_date(episode.publishing_date) %>
            <%= link [fa_icon("podcast"), " ", episode.podcast.title],
                           to: podcast_frontend_path(@conn, :show, episode.podcast),
                           class: "btn btn-default btn-xs truncate",
                           style: "color: #000" %>
            <%= link [fa_icon("headphones"), " ", episode.title],
                        to: episode_frontend_path(@conn, :show, episode),
                        class: "btn btn-primary btn-xs truncate" %>

              <%= for gig <- @grouped_gigs[episode] do %>
                <%= gig.role %>
              <% end %>

        <% end %>

<% end %>

<%= if @messages.total_entries > 0 do %>

Messages created by <%= @persona.name %>

      <%= pagination_links @conn, @messages, [Integer.to_string(@persona.id)],
                   path: &persona_frontend_path/4,
                   action: :show,
                   view_style: :bootstrap %>

        <%= for message <- @messages.entries do %>
          <li class="list-group-item message-<%= message.type %>">

              <%= if message.creator, do: message.creator.name, else: message.persona.name %>:

            <%= raw message.content %>
            <%= message.inserted_at %>

        <% end %>

<% end %>

<%= if @current_user && @current_user.podcaster == true  && @current_user.email_confirmed && @persona.email != nil do %>
  <%= link "Claim", to: persona_frontend_path(@conn, :claim, @persona),
                    class: "btn btn-normal",
                    method: :post,
                    data: [confirm: "Are you sure?"] %>

  <button class="btn btn-primary btn-sm"
          data-toggle="popover"
          data-placement="right"
          data-title="Personas"
          data-html="true"
          data-content="You can send an email to the owner of this persona and ask her for permission
                        to add you as a manifestation of this persona.

                        Your name, username and email address will be sent alongside in the email
                        to give the owner a chance to get in contact with you.">
    <%= fa_icon "info-circle" %> Help
  </button>
<% end %>


add recommendation text as quote when sharing on facebook

Recommendations

<%= if @podcast.recommendations != [] do %>
  <%= complain_link() %>

        User
        Recommendation
        Date

      <%= for recommendation <- @podcast.recommendations do %>

            <%= if @current_user && @current_user.id == recommendation.user_id do %>
              <nobr>
                <% text = "👍 " <> @podcast.title <> "%0A💬 " <> truncate_string(recommendation.comment, 220) <> "%0A🔊 " %>
                <% url = URI.encode_www_form(podcast_frontend_url(@conn, :show, @podcast)) %>
                <%= link "",  to: "https://twitter.com/intent/tweet?text=" <> text <>
                                  "&url=" <> url,
                              class: "social-button twitter-button",
                              title: "Tweet it" %>
                <%= link "",  to: "https://www.facebook.com/sharer/sharer.php?u=" <> url <> "&quote=" <> text,
                              class: "social-button facebook-button",
                              title: "Share on facebook" %>
                <%= link "",  to: "mailto:?subject=" <> text <> "&body=" <> url,
                              class: "social-button email-button",
                              title: "Send an E-Mail" %>
              </nobr>

            <% end %>
            <%= recommendation.user.name %>

          <%= recommendation.comment %>

            <%= PanWeb.PersonaFrontendView.format_date(recommendation.inserted_at) %>

      <% end %>

<% end %>

<%= render "_recommend_form.html",
           current_user: @current_user,
           changeset: @changeset,
           conn: @conn,
           podcast: @podcast %>

Recommendations

<%= if @podcast.recommendations != [] do %>
  <%= complain_link() %>

        User
        Recommendation
        Date

      <%= for recommendation <- @podcast.recommendations do %>

            <%= if @current_user && @current_user.id == recommendation.user_id do %>
              <nobr>
                <% text = "👍 " <> @podcast.title <> "%0A💬 " <> truncate_string(recommendation.comment, 220) <> "%0A🔊 " %>
                <% url = URI.encode_www_form(podcast_frontend_url(@conn, :show, @podcast)) %>
                <%= link "",  to: "https://twitter.com/intent/tweet?text=" <> text <>
                                  "&url=" <> url,
                              class: "social-button twitter-button",
                              title: "Tweet it" %>
                <%= link "",  to: "https://www.facebook.com/sharer/sharer.php?u=" <> url,
                              class: "social-button facebook-button",
                              title: "Share on facebook" %>
                <%= link "",  to: "mailto:?subject=" <> text <> "&body=" <> url,
                              class: "social-button email-button",
                              title: "Send an E-Mail" %>
              </nobr>

            <% end %>
            <%= recommendation.user.name %>

          <%= recommendation.comment %>

            <%= PanWeb.PersonaFrontendView.format_date(recommendation.inserted_at) %>

      <% end %>

<% end %>

<%= render "_recommend_form.html",
           current_user: @current_user,
           changeset: @changeset,
           conn: @conn,
           podcast: @podcast %>


Add footer links

Add footer links

<%= raw gettext("ElixirJobs lets you publish and find job offers to work developing Erlang/Elixir applications.") %>

<%= raw gettext("Proudly powered by %{elixir_link} and %{phoenix_link}.",
      elixir_link: "Elixir",
      phoenix_link: "Phoenix") %>

<%= raw gettext("Please contact Óscar de Arriba (%{odarriba_link}) or %{github_link} if anything seems broken or worthy of improvement.",
      odarriba_link: "@odarriba",
      github_link: "create a GitHub issue") %>

      <%= link(gettext("Post a job offer"), to: offer_path(@conn, :new)) %>
      |
      <%= link(gettext("About"), to: page_path(@conn, :about)) %>

      <%= link(gettext("All job offers"), to: offer_path(@conn, :index)) %>
      |
      <%= link(gettext("On site job offers"), to: offer_path(@conn, :index_filtered, "onsite")) %>
      |
      <%= link(gettext("Remote job offers"), to: offer_path(@conn, :index_filtered, "remote")) %>
      |
      <%= link(gettext("Full time job offers"), to: offer_path(@conn, :index_filtered, "full_time")) %>
      |
      <%= link(gettext("Part time job offers"), to: offer_path(@conn, :index_filtered, "part_time")) %>

<%= raw gettext("ElixirJobs lets you publish and find job offers to work developing Erlang/Elixir applications.") %>

<%= raw gettext("Proudly powered by %{elixir_link} and %{phoenix_link}.",
      elixir_link: "Elixir",
      phoenix_link: "Phoenix") %>

<%= raw gettext("Please contact Óscar de Arriba (%{odarriba_link}) or %{github_link} if anything seems broken or worthy of improvement.",
      odarriba_link: "@odarriba",
      github_link: "create a GitHub issue") %>

      <%= link(gettext("Job offers"), to: offer_path(@conn, :index)) %>
      |
      <%= link(gettext("Post a job offer"), to: offer_path(@conn, :new)) %>
      |
      <%= link(gettext("About"), to: page_path(@conn, :about)) %>


Fixes bug about use of wrong assignment

Fixes bug about use of wrong assignment

      Classes

      <%= link "New class", to: class_path(@conn, :new), class: "mdl-button mdl-js-button mdl-button--raised" %>

  <%= for term <- @terms do %>

            <%= term.name %>

            Class date
            Starting at
            Finishes at
            Classroom
            <%= if @conn.assigns.current_user.role == "Coordinator" do %>

            <% end %>

          <%= for offered_course <- term.offered_courses do %>

              <%= offered_course.course.name %>

            <%= Enum.with_index(offered_course.classes) |> Enum.map(fn {class,index} -> %>

                  <%= class.date %>

                  <%= class.date
                      |> Ecto.DateTime.from_date_and_time(class.starting_at)
                      |> Timex.format!("{h24}:{m}") %>

                  <%= class.date
                      |> Ecto.DateTime.from_date_and_time(class.finishes_at)
                      |> Timex.format!("{h24}:{m}") %>

                  <%= class.classroom %>

                <%= if @conn.assigns.current_user.role == "Coordinator" do %>

                    <button id="tr_menu_<%= class.id %>"
                            class="mdl-button mdl-js-button mdl-button--icon"
                    >
                      more_vert
                    </button>
                    <ul
                      class="
                        mdl-menu mdl-js-menu
                        <%=
                          if index > 10 and index > length(offered_course.classes)-4 do
                            'mdl-menu--top-right'
                          else
                            'mdl-menu--bottom-right'
                          end
                        %>
                      "
                      for="tr_menu_<%= class.id %>"
                    >

                        <%= link "Edit", to: class_path(@conn, :edit, class) %>

                        <%= link "Delete", to: class_path(@conn, :delete, class), method: :delete,
                          data: [confirm: """
                          Are you sure?
                          All the attendances of that class will be removed.
                          """] %>

                <% end %>

            <% end) %>
          <% end %>

  <% end %>

      Classes

      <%= link "New class", to: class_path(@conn, :new), class: "mdl-button mdl-js-button mdl-button--raised" %>

  <%= for term <- @terms do %>

            <%= term.name %>

            Class date
            Starting at
            Finishes at
            Classroom
            <%= if @conn.assigns.current_user.role == "Coordinator" do %>

            <% end %>

          <%= for offered_course <- term.offered_courses do %>

              <%= offered_course.course.name %>

            <%= Enum.with_index(offered_course.classes) |> Enum.map(fn {class,index} -> %>

                  <%= class.date %>

                  <%= class.date
                      |> Ecto.DateTime.from_date_and_time(class.starting_at)
                      |> Timex.format!("{h24}:{m}") %>

                  <%= class.date
                      |> Ecto.DateTime.from_date_and_time(class.finishes_at)
                      |> Timex.format!("{h24}:{m}") %>

                  <%= class.classroom %>

                <%= if @conn.assigns.current_user.role == "Coordinator" do %>

                    <button id="tr_menu_<%= class.id %>"
                            class="mdl-button mdl-js-button mdl-button--icon"
                    >
                      more_vert
                    </button>
                    <ul
                      class="
                        mdl-menu mdl-js-menu
                        <%=
                          if index > 10 and index > length(@classes)-4 do
                            'mdl-menu--top-right'
                          else
                            'mdl-menu--bottom-right'
                          end
                        %>
                      "
                      for="tr_menu_<%= class.id %>"
                    >

                        <%= link "Edit", to: class_path(@conn, :edit, class) %>

                        <%= link "Delete", to: class_path(@conn, :delete, class), method: :delete,
                          data: [confirm: """
                          Are you sure?
                          All the attendances of that class will be removed.
                          """] %>

                <% end %>

            <% end) %>
          <% end %>

  <% end %>


Use aliased SharedView

Use aliased SharedView

          <%= for {stock_type, _type_id, _stocks} <- @stock_by_type do %>
              <div class="<%= active(stock_type, @stock_by_type)%>">

                    <a href="#<%= stock_type %>" data-toggle="tab"> <%= stock_type %>

          <% end %>

          <%= for {stock_type, type_id, stocks} <- @stock_by_type do %>
              <%= render SharedView,
              "stock_type.html",
              stock_type: stock_type,
              type_id: type_id,
              stock_by_type: @stock_by_type,
              stocks: stocks,
              package: @package,
              credits: @credits
          %>
          <% end %>

        <%= gettext "Thank you for so much logging in!" %>

          <a class="btn btn-default" href="<%= page_path(@conn, :index, @conn.assigns.locale ) %>"><%= gettext "Back" %>
          <%= button(gettext("Log out"), to: user_selection_path(@conn, :delete, @conn.assigns[:user].id, method: :delete), method: "delete", class: "btn btn-default")  %>

      <%= for {stock_type, type_id, _stocks} <- @stock_by_type do %>

 <%= stock_type %> <%= gettext("remaining:") %>

        <span class="js-credit-count credit-type-<%= type_id %>" data-credit-type="<%= type_id %>" >
          <%=  @credits[stock_type] %>

      <%= end %>

        <%= gettext "Shopping Cart" %>

          <%= for distribution <- @distributions do %>
          <%= render SharedView, "distribution.html", distribution: distribution %>
          <% end %>

      <%= form_for @user_order, food_selection_path(@conn, :update, @conn.assigns.locale, @user_order.data.id), fn f -> %>
      <%= hidden_input(f, :finalized, value: true) %>
      <%= submit gettext("Complete your order!") %>
      <% end %>

          <%= for {stock_type, _type_id, _stocks} <- @stock_by_type do %>
              <div class="<%= active(stock_type, @stock_by_type)%>">

                    <a href="#<%= stock_type %>" data-toggle="tab"> <%= stock_type %>

          <% end %>

          <%= for {stock_type, type_id, stocks} <- @stock_by_type do %>
              <%= render OpenPantry.Web.SharedView,
              "stock_type.html",
              stock_type: stock_type,
              type_id: type_id,
              stock_by_type: @stock_by_type,
              stocks: stocks,
              package: @package,
              credits: @credits
          %>
          <% end %>

        <%= gettext "Thank you for so much logging in!" %>

          <a class="btn btn-default" href="<%= page_path(@conn, :index, @conn.assigns.locale ) %>"><%= gettext "Back" %>
          <%= button(gettext("Log out"), to: user_selection_path(@conn, :delete, @conn.assigns[:user].id, method: :delete), method: "delete", class: "btn btn-default")  %>

      <%= for {stock_type, type_id, _stocks} <- @stock_by_type do %>

 <%= stock_type %> <%= gettext("remaining:") %>

        <span class="js-credit-count credit-type-<%= type_id %>" data-credit-type="<%= type_id %>" >
          <%=  @credits[stock_type] %>

      <%= end %>

        <%= gettext "Shopping Cart" %>

          <%= for distribution <- @distributions do %>
          <%= render OpenPantry.Web.SharedView, "distribution.html", distribution: distribution %>
          <% end %>

      <%= form_for @user_order, food_selection_path(@conn, :update, @conn.assigns.locale, @user_order.data.id), fn f -> %>
      <%= hidden_input(f, :finalized, value: true) %>
      <%= submit gettext("Complete your order!") %>
      <% end %>


Add Google Analytics

Add Google Analytics

<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="Marc Addeo">

  <%= if assigns[:title] do %>
    <title><%= @title %> | marc.cx</title>
  <% else %>
    <title>marc.cx</title>
  <% end %>
    <link href="http://fonts.googleapis.com/css?family=Inconsolata:400,700|Open+Sans:300italic,400italic,700,300,800,400" rel="stylesheet" type="text/css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
    <link rel="stylesheet" href="<%= static_path(@conn, "/css/solarized_dark.css") %>">
    <link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">

  <%= if Mix.env == :prod do %>

  <% end %>

            <%= for item <- navigation(@conn) do %>
              <li role="presentation" <%= if item.active do %>class="active"<% end %>>
                <a href="<%= item.href %>"><%= item.text %>

            <% end %>

          <a href="<%= page_path(@conn, :index) %>" class="title text-muted">marc.cx

    <%= @inner %>

<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="Marc Addeo">

  <%= if assigns[:title] do %>
    <title><%= @title %> | marc.cx</title>
  <% else %>
    <title>marc.cx</title>
  <% end %>
    <link href="http://fonts.googleapis.com/css?family=Inconsolata:400,700|Open+Sans:300italic,400italic,700,300,800,400" rel="stylesheet" type="text/css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
    <link rel="stylesheet" href="<%= static_path(@conn, "/css/solarized_dark.css") %>">
    <link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">

            <%= for item <- navigation(@conn) do %>
              <li role="presentation" <%= if item.active do %>class="active"<% end %>>
                <a href="<%= item.href %>"><%= item.text %>

            <% end %>

          <a href="<%= page_path(@conn, :index) %>" class="title text-muted">marc.cx

    <%= @inner %>


admin menu

admin menu

  <button type="button"
          class="navbar-toggle collapsed"
          data-toggle="collapse"
          data-target="#navbar"
          aria-expanded="false"
          aria-controls="navbar">
    Toggle navigation

  </button>

  Panoptikum.io

<%= link "Home", to: category_frontend_path(@conn, :index) %>

About

Blog

<%= link "Podcasters", to: persona_frontend_path(@conn, :index) %>

<%= link "Users", to: user_frontend_path(@conn, :index) %>

<%= link ["Random ", fa_icon("podcast")], to: recommendation_frontend_path(@conn, :random) %>

    <%= if @current_user do %>
      <input type="checkbox" id="checkbox_toggle" class="drop">

        @<%= @current_user.username %>

<%= link "My Profile",  to: user_frontend_path(@conn, :my_profile)%>

<%= link "Change Password", to: user_frontend_path(@conn, :edit_password)%>

<%= link "My Messages", to: user_frontend_path(@conn, :my_messages)%>

<%= link "My Podcasts", to: user_frontend_path(@conn, :my_podcasts)%>

<%= link "My Recommendations", to: recommendation_frontend_path(@conn, :my_recommendations)%>

<%= link "My OPMLs",    to: opml_frontend_path(@conn, :index)%>

          @<%= @current_user.username %>

<%= link "My Profile",  to: user_frontend_path(@conn, :my_profile)%>

<%= link "Change Password", to: user_frontend_path(@conn, :edit_password)%>

<%= link "My Messages", to: user_frontend_path(@conn, :my_messages)%>

<%= link "My Podcasts", to: user_frontend_path(@conn, :my_podcasts)%>

<%= link "My Recommendations", to: recommendation_frontend_path(@conn, :my_recommendations)%>

<%= link "My OPMLs",    to: opml_frontend_path(@conn, :index)%>

      <%= if @current_user.admin do %>

            Admin

<%= link "Categories", to: category_path(@conn, :index) %>

<%= link "Podcasts", to: podcast_path(@conn, :index) %>

<%= link "Feeds", to: feed_path(@conn, :index) %>

<%= link "Feed Backlog", to: feed_backlog_path(@conn, :index) %>

<%= link "OPMLs", to: opml_path(@conn, :index) %>

<%= link "Users", to: user_path(@conn, :index) %>

<%= link "Messages", to: message_path(@conn, :index) %>

<%= link "Likes", to: like_path(@conn, :index) %>

<%= link "Follows", to: follow_path(@conn, :index) %>

<%= link "Subscriptions", to: subscription_path(@conn, :index) %>

<%= link "Recommendations", to: recommendation_path(@conn, :index) %>

<%= link "Personas", to: persona_path(@conn, :index) %>

<%= link "Gigs", to: gig_path(@conn, :index) %>

<%= link "Engagements", to: engagement_path(@conn, :index) %>

<%= link "Manifestations", to: manifestation_path(@conn, :index) %>

<%= link "Delegations", to: delegation_path(@conn, :index) %>

<%= link "Languages", to: language_path(@conn, :index) %>

      <% end %>

          <%= link "Log out", to: session_path(@conn, :delete, @current_user),
                              method: "delete" %>

    <% else %>

<%= link "Register", to: user_frontend_path(@conn, :new) %>

<%= link "Log in", to: session_path(@conn, :new) %>

    <% end %>

  <button type="button"
          class="navbar-toggle collapsed"
          data-toggle="collapse"
          data-target="#navbar"
          aria-expanded="false"
          aria-controls="navbar">
    Toggle navigation

  </button>

  Panoptikum.io

<%= link "Home", to: category_frontend_path(@conn, :index) %>

About

Blog

<%= link "Podcasters", to: persona_frontend_path(@conn, :index) %>

<%= link "Users", to: user_frontend_path(@conn, :index) %>

<%= link ["Random ", fa_icon("podcast")], to: recommendation_frontend_path(@conn, :random) %>

    <%= if @current_user do %>
      <input type="checkbox" id="checkbox_toggle" class="drop">

        @<%= @current_user.username %>

<%= link "My Profile",  to: user_frontend_path(@conn, :my_profile)%>

<%= link "Change Password", to: user_frontend_path(@conn, :edit_password)%>

<%= link "My Messages", to: user_frontend_path(@conn, :my_messages)%>

<%= link "My Podcasts", to: user_frontend_path(@conn, :my_podcasts)%>

<%= link "My Recommendations", to: recommendation_frontend_path(@conn, :my_recommendations)%>

<%= link "My OPMLs",    to: opml_frontend_path(@conn, :index)%>

          @<%= @current_user.username %>

<%= link "My Profile",  to: user_frontend_path(@conn, :my_profile)%>

<%= link "Change Password", to: user_frontend_path(@conn, :edit_password)%>

<%= link "My Messages", to: user_frontend_path(@conn, :my_messages)%>

<%= link "My Podcasts", to: user_frontend_path(@conn, :my_podcasts)%>

<%= link "My Recommendations", to: recommendation_frontend_path(@conn, :my_recommendations)%>

<%= link "My OPMLs",    to: opml_frontend_path(@conn, :index)%>

      <%= if @current_user.admin do %>

            Admin

<%= link "Categories", to: category_path(@conn, :index) %>

<%= link "Feed Backlog", to: feed_backlog_path(@conn, :index) %>

<%= link "Languages", to: language_path(@conn, :index) %>

<%= link "Podcasts", to: podcast_path(@conn, :index) %>

<%= link "Users", to: user_path(@conn, :index) %>

<%= link "OPMLs", to: opml_path(@conn, :index) %>

<%= link "Messages", to: message_path(@conn, :index) %>

<%= link "Likes", to: like_path(@conn, :index) %>

<%= link "Follows", to: follow_path(@conn, :index) %>

<%= link "Subscriptions", to: subscription_path(@conn, :index) %>

<%= link "Recommendations", to: recommendation_path(@conn, :index) %>

<%= link "Personas", to: persona_path(@conn, :index) %>

<%= link "Gigs", to: gig_path(@conn, :index) %>

<%= link "Engagements", to: engagement_path(@conn, :index) %>

<%= link "Manifestations", to: manifestation_path(@conn, :index) %>

<%= link "Delegations", to: delegation_path(@conn, :index) %>

      <% end %>

          <%= link "Log out", to: session_path(@conn, :delete, @current_user),
                              method: "delete" %>

    <% else %>

<%= link "Register", to: user_frontend_path(@conn, :new) %>

<%= link "Log in", to: session_path(@conn, :new) %>

    <% end %>


Modifying layout

Modifying layout

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="A platform for sharing stories.">
    <meta name="author" content="Marcus Bernales">

    <title>broadcast.love | worldwide</title>
    <link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">
  </head>

  <body>
    <div class="container">
      <main role="main" id="root">
      </main>
    </div> <!-- /container -->
    <script src="<%= static_path(@conn, "/js/app.js") %>"></script>
    <script src="http://localhost:4001/build/app.hot.js"></script>
  </body>
</html>

<!DOCTYPE html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="A platform for sharing stories.">
    <meta name="author" content="Marcus Bernales">

    <title>broadcast.love | worldwide</title>
    <link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">

Get Started

<%= get_flash(@conn, :info) %>

<%= get_flash(@conn, :error) %>

        <%= render @view_module, @view_template, assigns %>


parentheses

parentheses

<script>localStorage.setItem("csrfToken", "<%= get_csrf_token() %>");</script>

<script>localStorage.setItem("csrfToken", "<%= get_csrf_token %>");</script>


format event list

format event list

<%= if length(@memberships) == 0 do %>

No events available

Create your own event.

    <%= link "Create event", to: account_event_path(@conn, :new), class: "btn btn-outline-primary" %>

<% else %>

        Public
        Name
        Date

      <%= for membership <- @memberships do %>

          <%= membership.event.public %>

            <%= link membership.event.name, to: classroom_dashboard_path(@conn, :show, membership.event) %>

              <%= render_markdown truncate(membership.event.description_markdown, 200), escape: true %>

            <%= l(Calendar.DateTime.to_date(membership.event.starts_at)) %> -
            <%= l(Calendar.DateTime.to_date(membership.event.ends_at)) %>

            <%= if membership.role.id != 1 do %>
              <%= link "Delete", to: account_membership_path(@conn, :delete, membership), method: :delete, data: [toggle: "modal", target: "baseModal"], class: "btn btn-outline-danger btn-sm" %>
            <% end %>
            <%#= if membership.role.id == 1 do %>
              <%#= link "copy", to: account_event_event_copy_path(@conn, :show, membership.event), class: "btn btn-sm btn-outline-success" %>
            <%# end %>

      <% end %>

<% end %>


Style alert message for mobile

Style alert message for mobile

<%
input_class = "ba b--blue br3 tc pv3 ph3 f5 outline-0 dark-red mb2 w-80-ns w-100"
home_tile_class = "w-60-ns tc flex flex-column items-center mv4-ns mh4-ns pb3-ns"
%>

Our practitioners offer free advice and support – ask us your parenting questions

As a parent of an under five do you struggle to find out who to get help from or feel you don't know what questions to ask?

We're here for you, whatever's on your mind. We'll support you as often or as little as you want

We can give you help with your child’s development, behaviour, feeding, family life, wellbeing, understanding your child, sleeping, and much more.

You can speak to the same practitioner as regularly as you like – continuing your conversation where you left off, without having to explain your situation from the beginning every time.

<%= get_flash(@conn, :error) %>

      <div class="<%= "#{home_tile_class} pb4" %>">

Speak to us

Speak to our practitioners online, or by phone. Once you've spoken, you can arrange to speak to the same practitioner again.

        <%= form_for @conn, user_path(@conn, :create), [as: :user], fn f -> %>
          <%= text_input f, :email, placeholder: "Your email", class: input_class %>
          <%= submit "Talk to a practitioner", class: red_button() %>
        <% end %>

      <div class="<%= "#{home_tile_class} pb3" %>">

Continue a conversation

Spoken to one of our practitioners before? Login to speak with them again. Forgotten your code? Request a new code

        <%= form_for @conn, session_path(@conn, :create), [as: :session], fn f -> %>
          <%= text_input f, :email, placeholder: "Your email", class: input_class %>
          <%= text_input f, :uuid, placeholder: "Code", class: input_class %>
          <%= submit "Login", class: red_button() %>
        <% end %>

Our practitioners

We have years of experience working with families and are here to support you

    <%= link to: page_path(@conn, :practitioners), class: "db w-100" do %>
      <button class="<%= red_button() %>">Meet our practitioners</button>
    <% end %>


Trying to framebust links from lessonplans

            <link rel='stylesheet' href='/lessonplans/css/<%= raw @css %>.css'>
    <link rel="stylesheet" href="/css/main.css">

<a href="<%= ParamSession.gen_url(@conn, "/lessondesigns/sidebar") %>" style="color:#fff">Back to the list of lesson plans | Jump to comments

        <%= raw String.replace(@lesson, "<a href", "

        <%= render Survey.CommentstreamView, "_comments.html", comments: @comments, conn: @conn %>

            <link rel='stylesheet' href='/lessonplans/css/<%= raw @css %>.css'>
    <link rel="stylesheet" href="/css/main.css">

<a href="<%= ParamSession.gen_url(@conn, "/lessondesigns/sidebar") %>" style="color:#fff">Back to the list of lesson plans | Jump to comments

        <%= raw @lesson %>

        <%= render Survey.CommentstreamView, "_comments.html", comments: @comments, conn: @conn %>


add community link to header

add community link to header

    <%= if assigns[:logo] == nil || assigns[:logo] == true do %>
      <img src='/images/logo.svg' alt="<%= gettext("SignDict Logo") %>" class="so-navigation__logo"/>
      <%= gettext("About SignDict")%>
    <% else %>
      <%= gettext("About SignDict")%>
    <% end %>

    <input class="so-navigation__menu-btn" hidden type="checkbox" id="so-navigation__menu-btn" />

    <%= if assigns[:logo] == nil || assigns[:logo] == true do %>

    <% else %>

    <% end %>

      <%= if @current_user do %>
        <%= if Canada.Can.can? @current_user, :show_backend, %{} do %>

            <%= link "Admin", to: backend_dashboard_path(@conn, :index), data: [turbolinks: "false"] %>

        <% end %>

          <%= form_tag(session_path(@conn, :delete, @current_user), method: :delete) %>
            <input type="submit" value="<%= gettext("Sign out") %>" class='sc-link so-navigation__menu-item--logout' />
          </form>

          Community

        <%= if Gettext.get_locale(SignDict.Gettext) == "de" do %>
          English
        <% else %>
          Deutsch
        <% end %>

          <a href="<%= user_path(@conn, :show, @current_user) %>"><%= img_tag SignDict.User.avatar_url(@current_user), alt: gettext("The avatar image of this user"), class: "so-navigation__user-avatar" %><%= @current_user.name %>

      <% else %>

          <%= link gettext("Register"), to: user_path(@conn, :new) %>

          <%= link gettext("Sign in"), to: session_path(@conn, :new) %>

          Community

          <%= if Gettext.get_locale(SignDict.Gettext) == "de" do %>
            English
          <% else %>
            Deutsch
          <% end %>

      <% end %>

    <%= if assigns[:logo] == nil || assigns[:logo] == true do %>
      <img src='/images/logo.svg' alt="<%= gettext("SignDict Logo") %>" class="so-navigation__logo"/>
      <%= gettext("About SignDict")%>
    <% else %>
      <%= gettext("About SignDict")%>
    <% end %>

    <input class="so-navigation__menu-btn" hidden type="checkbox" id="so-navigation__menu-btn" />

    <%= if assigns[:logo] == nil || assigns[:logo] == true do %>

    <% else %>

    <% end %>

      <%= if @current_user do %>
        <%= if Canada.Can.can? @current_user, :show_backend, %{} do %>

            <%= link "Admin", to: backend_dashboard_path(@conn, :index), data: [turbolinks: "false"] %>

        <% end %>

          <%= form_tag(session_path(@conn, :delete, @current_user), method: :delete) %>
            <input type="submit" value="<%= gettext("Sign out") %>" class='sc-link so-navigation__menu-item--logout' />
          </form>

        <%= if Gettext.get_locale(SignDict.Gettext) == "de" do %>
          English
        <% else %>
          Deutsch
        <% end %>

          <a href="<%= user_path(@conn, :show, @current_user) %>"><%= img_tag SignDict.User.avatar_url(@current_user), alt: gettext("The avatar image of this user"), class: "so-navigation__user-avatar" %><%= @current_user.name %>

      <% else %>

          <%= link gettext("Register"), to: user_path(@conn, :new) %>

          <%= link gettext("Sign in"), to: session_path(@conn, :new) %>

          <%= if Gettext.get_locale(SignDict.Gettext) == "de" do %>
            English
          <% else %>
            Deutsch
          <% end %>

      <% end %>