boot: run pre_start hooks when running commands (#158)

#!/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=$(greadlink -f "$0")
  else
    SCRIPT=$(my_readlink_f "$0" )
  fi
else
  SCRIPT=$(readlink -f "$0" )
fi

# Parent directory of this script
SCRIPT_DIR=$(dirname "${SCRIPT}")
# Root directory of all releases
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="<%= release_name %>"
# Current version of the release
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 %>"<% 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="$RELEASE_ROOT_DIR/releases/start_erl.data"
# Directory containing the current version of this release
REL_DIR="$RELEASE_ROOT_DIR/releases/$REL_VSN"
# The lib directory for this release
REL_LIB_DIR="$RELEASE_ROOT_DIR/lib"
# Options passed to erl
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=""

# Pre-start/stop event hook paths
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

    "$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 determining the version of ERTS available to the release
# This is only ever called if ERTS_VSN is not set
_detect_erts_vsn() {
    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
    "$__erl" -boot start_clean -eval 'Ver = erlang:system_info(version), io:format("~s~n", [Ver]), halt()' -noshell
}

# 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. For setting ERTS_DIR and ROOTDIR
_find_erts_dir() {
    __erts_dir="$RELEASE_ROOT_DIR/erts-$ERTS_VSN"
    if [ -d "$__erts_dir" ]; then
        ERTS_DIR="$__erts_dir";
        ROOTDIR="$RELEASE_ROOT_DIR"
    else
        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
        code="io:format(\"~s\", [code:root_dir()]), halt()."
        __erl_root="$("$__erl" -noshell -eval "$code")"
        ERTS_DIR="$__erl_root/erts-$ERTS_VSN"
        ROOTDIR="$__erl_root"
    fi
}

# 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} occurances 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
}

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

# If ERTS_VSN is not set, detect it
if [ -z "$ERTS_VSN" ]; then
    ERTS_VSN="$(_detect_erts_vsn)"
    echo "$ERTS_VSN $REL_VSN" > "$START_ERL_DATA"
fi

# Allow override of where to read configuration from
# By default it's RELEASE_ROOT_DIR
if [ -z "$RELEASE_CONFIG_DIR" ]; then
    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"

# 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
        VMARGS_PATH="$RELEASE_CONFIG_DIR/vm.args"
    else
        VMARGS_PATH="$REL_DIR/vm.args"
    fi
fi
if [ "$VMARGS_PATH" != "$RELEASE_MUTABLE_DIR/vm.args" ]; then
    echo "#### Generated - edit/create $RELEASE_CONFIG_DIR/vm.args instead." \
        >  "$RELEASE_MUTABLE_DIR/vm.args"
    cat  "$VMARGS_PATH"                              \
        >> "$RELEASE_MUTABLE_DIR/vm.args"
    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
        SYS_CONFIG_PATH="$RELEASE_CONFIG_DIR/sys.config"
    else
        SYS_CONFIG_PATH="$REL_DIR/sys.config"
    fi
fi
if [ "$SYS_CONFIG_PATH" != "$RELEASE_MUTABLE_DIR/sys.config" ]; then
    echo "%% Generated - edit/create $RELEASE_CONFIG_DIR/sys.config instead." \
        >  "$RELEASE_MUTABLE_DIR/sys.config"
    cat  "$SYS_CONFIG_PATH"                              \
        >> "$RELEASE_MUTABLE_DIR/sys.config"
    SYS_CONFIG_PATH=$RELEASE_MUTABLE_DIR/sys.config
fi
if [ $REPLACE_OS_VARS ]; then
    _replace_os_vars "$SYS_CONFIG_PATH"
fi

# Extract the target node name from node.args
# Should be `-sname somename` or `-name somename@somehost`
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
NAME_TYPE="$(echo "$NAME_ARG" | awk '{print $1}')"
# NAME will be either `somename` or `somename@somehost`
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

_find_erts_dir
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"
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

# 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_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_START_HOOKS"
        ## Restart the VM without exiting the process
        if ! nodetool "restart"; then
            exit 1
        fi
        ;;

    reboot)
        _check_cookie
        _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
        ;;

    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"

        _run_hooks_from_dir "$PRE_UPGRADE_HOOKS"

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

        _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_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_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="$@"

        _run_hooks_from_dir "$PRE_START_HOOKS"

        # 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 "$?"
        ;;
    *)
        __command_path="$REL_DIR/commands/$1"
        if [ -f "$__command_path" ]; then
            _check_cookie
            . "$__command_path"
        else
            echo "Usage: $REL_NAME {start|start_boot <file>|foreground|stop|restart|reboot|pid|ping|console|console_clean|console_boot <file>|attach|remote_console|upgrade|downgrade|install|escript|rpc|rpcterms|eval|command <module> <function> <args>}"
            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=$(greadlink -f "$0")
  else
    SCRIPT=$(my_readlink_f "$0" )
  fi
else
  SCRIPT=$(readlink -f "$0" )
fi

# Parent directory of this script
SCRIPT_DIR=$(dirname "${SCRIPT}")
# Root directory of all releases
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="<%= release_name %>"
# Current version of the release
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 %>"<% 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="$RELEASE_ROOT_DIR/releases/start_erl.data"
# Directory containing the current version of this release
REL_DIR="$RELEASE_ROOT_DIR/releases/$REL_VSN"
# The lib directory for this release
REL_LIB_DIR="$RELEASE_ROOT_DIR/lib"
# Options passed to erl
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=""

# Pre-start/stop event hook paths
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

    "$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 determining the version of ERTS available to the release
# This is only ever called if ERTS_VSN is not set
_detect_erts_vsn() {
    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
    "$__erl" -boot start_clean -eval 'Ver = erlang:system_info(version), io:format("~s~n", [Ver]), halt()' -noshell
}

# 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. For setting ERTS_DIR and ROOTDIR
_find_erts_dir() {
    __erts_dir="$RELEASE_ROOT_DIR/erts-$ERTS_VSN"
    if [ -d "$__erts_dir" ]; then
        ERTS_DIR="$__erts_dir";
        ROOTDIR="$RELEASE_ROOT_DIR"
    else
        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
        code="io:format(\"~s\", [code:root_dir()]), halt()."
        __erl_root="$("$__erl" -noshell -eval "$code")"
        ERTS_DIR="$__erl_root/erts-$ERTS_VSN"
        ROOTDIR="$__erl_root"
    fi
}

# 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} occurances 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
}

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

# If ERTS_VSN is not set, detect it
if [ -z "$ERTS_VSN" ]; then
    ERTS_VSN="$(_detect_erts_vsn)"
    echo "$ERTS_VSN $REL_VSN" > "$START_ERL_DATA"
fi

# Allow override of where to read configuration from
# By default it's RELEASE_ROOT_DIR
if [ -z "$RELEASE_CONFIG_DIR" ]; then
    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"

# 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
        VMARGS_PATH="$RELEASE_CONFIG_DIR/vm.args"
    else
        VMARGS_PATH="$REL_DIR/vm.args"
    fi
fi
if [ "$VMARGS_PATH" != "$RELEASE_MUTABLE_DIR/vm.args" ]; then
    echo "#### Generated - edit/create $RELEASE_CONFIG_DIR/vm.args instead." \
        >  "$RELEASE_MUTABLE_DIR/vm.args"
    cat  "$VMARGS_PATH"                              \
        >> "$RELEASE_MUTABLE_DIR/vm.args"
    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
        SYS_CONFIG_PATH="$RELEASE_CONFIG_DIR/sys.config"
    else
        SYS_CONFIG_PATH="$REL_DIR/sys.config"
    fi
fi
if [ "$SYS_CONFIG_PATH" != "$RELEASE_MUTABLE_DIR/sys.config" ]; then
    echo "%% Generated - edit/create $RELEASE_CONFIG_DIR/sys.config instead." \
        >  "$RELEASE_MUTABLE_DIR/sys.config"
    cat  "$SYS_CONFIG_PATH"                              \
        >> "$RELEASE_MUTABLE_DIR/sys.config"
    SYS_CONFIG_PATH=$RELEASE_MUTABLE_DIR/sys.config
fi
if [ $REPLACE_OS_VARS ]; then
    _replace_os_vars "$SYS_CONFIG_PATH"
fi

# Extract the target node name from node.args
# Should be `-sname somename` or `-name somename@somehost`
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
NAME_TYPE="$(echo "$NAME_ARG" | awk '{print $1}')"
# NAME will be either `somename` or `somename@somehost`
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

_find_erts_dir
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"
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

# 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_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_START_HOOKS"
        ## Restart the VM without exiting the process
        if ! nodetool "restart"; then
            exit 1
        fi
        ;;

    reboot)
        _check_cookie
        _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
        ;;

    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"

        _run_hooks_from_dir "$PRE_UPGRADE_HOOKS"

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

        _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_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_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 "$?"
        ;;
    *)
        __command_path="$REL_DIR/commands/$1"
        if [ -f "$__command_path" ]; then
            _check_cookie
            . "$__command_path"
        else
            echo "Usage: $REL_NAME {start|start_boot <file>|foreground|stop|restart|reboot|pid|ping|console|console_clean|console_boot <file>|attach|remote_console|upgrade|downgrade|install|escript|rpc|rpcterms|eval|command <module> <function> <args>}"
            exit 1
        fi
        ;;
esac

exit 0


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="">

    <title>Ephemeral Hosting</title>
    <link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">

Currently Viewing: 0

        <%= @inner %>


A less colorful version of the animals page

        Animals

        View Animals

        Add Animals

        Animal Help

        Filter by...

Name

              <input class="input" type="text" value="">

Species

                <select>
                  <option value="bovine">Bovine</option>
                  <option value="equine" selected>Equine</option>
                </select>

Tags

              <input class="input" type="text" value="">

                <input type="checkbox">
                Include animals not in service

      Athena (equine)

        mare

      Jake (equine)

        gelding

      Editing Ross

    <form>

      Name

        <input class="input" type="text" value="Ross">

      Tags

            stallion
            <button class="delete is-small"></button>

            aggressive
            <button class="delete is-small"></button>

          <input class="input" type="text" placeholder="Add a tag" size="12">

      Species

          <select>
            <option value="bovine">Bovine</option>
            <option value="equine" selected>Equine</option>
          </select>

        Date added

          <input class="input" type="text" value="3-Aug-2016">

        End of service

          <input class="input" type="text" value="unscheduled">

    </form>

      Save

      Cancel

      Xena (equine)

          mare

          see notes

          skittish

        Added 1 Jan 2016

    Edit
    Add animals like this one


Add grouping info to meeting minutes page

Sitzungsprotokolle

  Hier findest du die Protokolle der LW-Konferenzen.

Verbund 2 (ehemals “Nord- und Osteuropa”)

    <%= document_link("LW 2019 Prag", Routes.static_path(Endpoint, "/resources/LW-Protokoll 2019.pdf")) %>

    <%= document_link("LW 2018 Stockholm", Routes.static_path(Endpoint, "/resources/LW-Protokoll 2018.pdf")) %>

    <%= document_link("LW 2017 Brüssel", Routes.static_path(Endpoint, "/resources/LW-Protokoll 2017.pdf")) %>

    <%= document_link("LW 2016 Helsinki", Routes.static_path(Endpoint, "/resources/LW-Protokoll 2016.pdf")) %>

    <%= document_link("LW 2015 Paris", Routes.static_path(Endpoint, "/resources/LW-Protokoll 2015.pdf")) %>

    <%= document_link("LW 2014 Kopenhagen", Routes.static_path(Endpoint, "/resources/LW-Protokoll 2014.pdf")) %>

Sitzungsprotokolle

  Hier findest du die Protokolle der Konferenzen beim Landeswettbewerb.

    <%= document_link("LW 2014 Kopenhagen", Routes.static_path(Endpoint, "/resources/LW-Protokoll 2014.pdf")) %>

    <%= document_link("LW 2015 Paris", Routes.static_path(Endpoint, "/resources/LW-Protokoll 2015.pdf")) %>

    <%= document_link("LW 2016 Helsinki", Routes.static_path(Endpoint, "/resources/LW-Protokoll 2016.pdf")) %>

    <%= document_link("LW 2017 Brüssel", Routes.static_path(Endpoint, "/resources/LW-Protokoll 2017.pdf")) %>

    <%= document_link("LW 2018 Stockholm", Routes.static_path(Endpoint, "/resources/LW-Protokoll 2018.pdf")) %>

    <%= document_link("LW 2019 Prag", Routes.static_path(Endpoint, "/resources/LW-Protokoll 2019.pdf")) %>


Maybe xml readers are even dumber then browsers.

<item>
  <title><%= title(@editorial) %></title>
  <description>
    <![CDATA[
      <img src="<%= image_url(@editorial) %>"/>

<%= description(@editorial) %>

    ]]>
  </description>
  <link><%= editorial_link(@editorial) %></link>
  <guid isPermaLink="false"><%= guid(@editorial) %></guid>
  <enclosure url="<%= image_url(@editorial) %>" type="<%= image_type(@editorial) %>" length="<%= image_length(@editorial) %>" />
  <%= for category <- categories(@editorial) do %>
    <category><%= category %></category>
  <% end %>
</item>


fix: link to correct pub key path

fix: link to correct pub key path

<img src="<%= static_path(@conn, "/images/christian-kruse.jpg") %>" alt="" class="u-photo big">

Christian Kruse

      My name is Christian Kruse. I work as a software developer and
      system administator at <%= link "Termitel GmbH", to: "https://termitel.de/" %>.
      I live in Germany in a small town called
      <%= link "Steinfurt", to: "https://en.wikipedia.org/wiki/Steinfurt" %>.

      I am passionate about software development,
      <%= link "Linux", to: "https://en.wikipedia.org/wiki/Linux" %>,
      <%= link "FLOSS", to: "https://en.wikipedia.org/wiki/Free_and_open-source_software" %>
      as well as <%= link "OS X", to: "https://en.wikipedia.org/wiki/OS_X" %>.
      I am also a do-it-yourself apologetic: I did a lot of things in and
      around my house myself. I love the hacker culture. And last but not
      least I am a dog owner.

      This is my personal replacement for Twitter, Facebook and the other
      data silos. <%= link "My content is mine", to: "http://indiewebcamp.com/" %>
      — so if you are interested in my activity, just have a look at this
      page.

Personal information

Address

Christian Kruse

Friedenau 35

48565 Steinfurt

Germany

Email

<%= link "cjk@defunct.ch", to: "mailto:cjk@defunct.ch", class: "u-email" %>

Jabber

<%= link "cjk@defunct.ch", to: "xmpp:cjk@defunct.ch" %>

PGP

A99A9D73

BC5D 9F4E F7FB 4382 6056  E834 B8E0 F342 A99A 9D73

<%= link "wwwtech.de/A99A9D73.asc", to: "/A99A9D73.asc" %>

Please send me encrypted mails if possible (see my public key above). Every
    bit of encrypted traffic increases the encrypted background noise
    and thus makes it harder to distinguish between important and
    unimportant traffic.

Social media

I also take part in several social services:

<%= link "forum.selfhtml.org/users/1", to: "http://forum.selfhtml.org/users/1", rel: "me" %> on SELFHTML

<%= link "@cjk101010", to: "https://twitter.com/cjk101010", rel: "me" %> on Twitter

<%= link "github.com/ckruse", to: "https://github.com/ckruse", rel: "me" %> on Github

<%= link "flattr.com/profile/cjk", to: "https://flattr.com/profile/cjk", rel: "me" %> on Flattr

<%= link "www.reddit.com/user/cjk101010/", to: "https://www.reddit.com/user/cjk101010/", rel: "me" %> on Reddit

<%= link "news.ycombinator.com/user?id=cjk101010", to: "https://news.ycombinator.com/user?id=cjk101010", rel: "me" %> on Hackernews

<%= link "keybase.io/ckruse", to: "https://keybase.io/ckruse", rel: "me" %> on Keybase.io

<%= link "stackoverflow.com/users/785998/ckruse", to: "http://stackoverflow.com/users/785998/ckruse", rel: "me" %> on StackOverflow

<img src="<%= static_path(@conn, "/images/christian-kruse.jpg") %>" alt="" class="u-photo big">

Christian Kruse

      My name is Christian Kruse. I work as a software developer and
      system administator at <%= link "Termitel GmbH", to: "https://termitel.de/" %>.
      I live in Germany in a small town called
      <%= link "Steinfurt", to: "https://en.wikipedia.org/wiki/Steinfurt" %>.

      I am passionate about software development,
      <%= link "Linux", to: "https://en.wikipedia.org/wiki/Linux" %>,
      <%= link "FLOSS", to: "https://en.wikipedia.org/wiki/Free_and_open-source_software" %>
      as well as <%= link "OS X", to: "https://en.wikipedia.org/wiki/OS_X" %>.
      I am also a do-it-yourself apologetic: I did a lot of things in and
      around my house myself. I love the hacker culture. And last but not
      least I am a dog owner.

      This is my personal replacement for Twitter, Facebook and the other
      data silos. <%= link "My content is mine", to: "http://indiewebcamp.com/" %>
      — so if you are interested in my activity, just have a look at this
      page.

Personal information

Address

Christian Kruse

Friedenau 35

48565 Steinfurt

Germany

Email

<%= link "cjk@defunct.ch", to: "mailto:cjk@defunct.ch", class: "u-email" %>

Jabber

<%= link "cjk@defunct.ch", to: "xmpp:cjk@defunct.ch" %>

PGP

A99A9D73

BC5D 9F4E F7FB 4382 6056  E834 B8E0 F342 A99A 9D73

<%= link "wwwtech.de/A99A9D73.asc", to: static_path(@conn, "/A99A9D73.asc") %>

Please send me encrypted mails if possible (see my public key above). Every
    bit of encrypted traffic increases the encrypted background noise
    and thus makes it harder to distinguish between important and
    unimportant traffic.

Social media

I also take part in several social services:

<%= link "forum.selfhtml.org/users/1", to: "http://forum.selfhtml.org/users/1", rel: "me" %> on SELFHTML

<%= link "@cjk101010", to: "https://twitter.com/cjk101010", rel: "me" %> on Twitter

<%= link "github.com/ckruse", to: "https://github.com/ckruse", rel: "me" %> on Github

<%= link "flattr.com/profile/cjk", to: "https://flattr.com/profile/cjk", rel: "me" %> on Flattr

<%= link "www.reddit.com/user/cjk101010/", to: "https://www.reddit.com/user/cjk101010/", rel: "me" %> on Reddit

<%= link "news.ycombinator.com/user?id=cjk101010", to: "https://news.ycombinator.com/user?id=cjk101010", rel: "me" %> on Hackernews

<%= link "keybase.io/ckruse", to: "https://keybase.io/ckruse", rel: "me" %> on Keybase.io

<%= link "stackoverflow.com/users/785998/ckruse", to: "http://stackoverflow.com/users/785998/ckruse", rel: "me" %> on StackOverflow


Update index.html.eex

Update index.html.eex

Welcome to Phoenix!

Most web frameworks make you choose between speed and a productive environment. Phoenix and Elixir give you both.

Resources

        Guides

        Docs

        Source

Help

        Mailing list

        Issues

        #elixir-lang on freenode IRC

        @elixirphoenix

Welcome to Phoenix!

Most frameworks make you choose between speed and a productive environment. Phoenix and Elixir give you both.

Resources

        Guides

        Docs

        Source

Help

        Mailing list

        Issues

        #elixir-lang on freenode IRC

        @elixirphoenix


Give graphs titles instead of using headlines

<!DOCTYPE html>

    <meta http-equiv="content-type" content="text/html; charset=utf8">

Comparison

Data Table

              Name
              Iterations per Second
              Average
              Deviation
              median

            <%= for {name, statistics} <- suite.statistics do %>

                <%= name %>
                <%= statistics.ips %>
                <%= statistics.average %>
                <%= statistics.std_dev_ratio %>%
                <%= statistics.median %>

            <% end %>

    <%= for {name, _} <- suite.run_times do %>

 <%= name %>

          <div class="sorted-run-times" data-job-name="<%= name %>">

          <div class="raw-run-times" data-job-name="<%= name %>">

    <% end %>

<!DOCTYPE html>

    <meta http-equiv="content-type" content="text/html; charset=utf8">

Comparison

Data Table

              Name
              Iterations per Second
              Average
              Deviation
              median

            <%= for {name, statistics} <- suite.statistics do %>

                <%= name %>
                <%= statistics.ips %>
                <%= statistics.average %>
                <%= statistics.std_dev_ratio %>%
                <%= statistics.median %>

            <% end %>

Iterations per Second

Runtime Box Plot

    <%= for {name, _} <- suite.run_times do %>

 <%= name %>

 Run time Histogram

          <div class="sorted-run-times" data-job-name="<%= name %>">

 Raw run times

          <div class="raw-run-times" data-job-name="<%= name %>">

    <% end %>


category search: ok

category search: ok

  You can mask your search terms with an asterisk at the end or the beginning of the search term,
  as long as there are 3 characters left.

  So "sciece", "sci*", "*sci" or "*ien*" will work, while "*ce" will not.

 Search results - Categories

<%= for hit <- @hits["hits"] do %>

    <%= fa_icon("folder-o") %> Category
    <%= link hit["_source"]["title"], to: category_frontend_path(PanWeb.Endpoint, :show, hit["_id"]) %>

<%= link category_frontend_url(PanWeb.Endpoint, :show, hit["_id"]),
               to: category_frontend_url(PanWeb.Endpoint, :show, hit["_id"]) %>

<% end %>


publish transactions

publish transactions

Transaction Information

  <span class="fa <%= get_icon(@transaction.type) %>">
  <%= get_type(@transaction.type) %>
  | Hash:
  <%= @transaction.txid %>

<a href="<%= transactions_path(@conn, :index) %>" alt="Back to all transactions" title="Back to all transactions" class="back-link"><%= gettext "Back to all transactions" %>

      <%= if @transaction.type == "ClaimTransaction" do %>

<%= gettext "Claimed from" %>

        <%= for input <- @transaction.claims do %>

            <a href="<%= address_path(@conn, :index, input.address_hash)%>" alt="View wallet address" title="View wallet address" class="large-blue-link wallet-address"><%= input.address_hash %>

<%= Helpers.round_or_not(input.value) %> <%= Api.get_asset_name(input.asset) %>

        <% end %>
      <% end %>
      <%= if @transaction.type != "ClaimTransaction" and @transaction.vin != []  do %>

<%= gettext "Sent from" %>

        <%= for input <- @transaction.vin do %>

    				<a href="<%= address_path(@conn, :index, input.address_hash)%>" alt="View wallet address" title="View wallet address" class="large-blue-link wallet-address"><%= input.address_hash %>

<%= Helpers.round_or_not(input.value) %> <%= Api.get_asset_name(input.asset) %>

        <% end %>
      <% end %>

		<img src="<%= static_path(@conn, "/images/ICON_Sent-arrow.svg")%>" alt="Sent arrow" title="Sent arrow" class="transaction-sent-arrow" />

      <%= if @transaction.vouts != [] do %>

<%= gettext "Sent to" %>

        <%= for vout <- @transaction.vouts do %>

    				<a href="<%= address_path(@conn, :index, vout.address_hash)%>" alt="View wallet address" title="View wallet address" class="large-blue-link wallet-address"><%= vout.address_hash %>

<%= Helpers.round_or_not(vout.value) %> <%= Api.get_asset_name(vout.asset) %>

        <% end %>
      <% end %>
      <%= if @transaction.type == "RegisterTransaction" do %>

<%= gettext "Registered" %>

          <a href="<%= address_path(@conn, :index, @transaction.asset.admin)%>" alt="View wallet address" title="View wallet address" class="large-blue-link wallet-address"><%= @transaction.asset.admin %>

<%= Helpers.round_or_not(@transaction.asset.amount) %> <%= Api.get_asset_name(@transaction.txid) %>

      <% end %>

<%= gettext "Time" %>

<%= compare_time_and_get_minutes(@transaction.time) %>

      <%= get_explanation("transaction_time") %>

<%= gettext "Network Fee" %>

<%= @transaction.net_fee %>

      <%= get_explanation("transaction_network_fees") %>

<%= gettext "System Fee" %>

<%= @transaction.sys_fee %>

      <%= get_explanation("transaction_system_fees") %>

<%= gettext "Included in Block" %>

<a href="<%= block_path( @conn, :index, @transaction.block_hash) %>" alt="View transaction" title="View transaction" class="large-blue-link col-4-width"><%= @transaction.block_height %>

<%= gettext "Size" %>

<%= @transaction.size %> <%= gettext "bytes" %>

      <%= get_explanation("transaction_size") %>

  <%= if @transaction.contractt != nil do %>

<%= gettext "Bytecode Script" %>

<%= @transaction.contract %>

  <% end %>

<%= gettext "Bytecode Invocation Script" %>

      <%= get_explanation("bytecode_invocation_script") %>

			<%= for script <- @transaction.scripts do %>

<%= get_inv(script) %>

			<% end %>

<%= gettext "Bytecode Verification Script" %>

      <%= get_explanation("bytecode_verification_script") %>

			<%= for script <- @transaction.scripts do %>

<%= get_ver(script) %>

			<% end %>

  <%= if @transaction.attributes != [] do %>
		<%= for att <- @transaction.attributes do %>

<%= gettext "Atributte: " %> <%=att["usage"]%>

<%= att["data"] %>

		<% end %>
  <% end %>
  <%= if @transaction.script != nil do %>

<%= gettext "Bytecode Script" %>

<%= @transaction.script %>

  <% end %>

<%= gettext "Opcode Invocation Script" %>

      <%= get_explanation("opcode_invocation_script") %>

        <%= for script <- @transaction.scripts do %>
          <%= for operation <- parse_invocation(script) do %>
            <%= operation %>
          <% end %>
        <% end %>

<%= gettext "Opcode Verification Script" %>

      <%= get_explanation("opcode_verification_script") %>

        <%= for script <- @transaction.scripts do %>
          <%= for operation <- parse_verification(script) do %>
            <%= operation %>
          <% end %>
        <% end %>

  <%= if @transaction.attributes != [] do %>
		<%= for att <- @transaction.attributes do %>

<%= gettext "Opcode Attribute:" %> <%=att["usage"]%>

<%= Disassembler.parse_script(att["data"]) %>

		<% end %>
  <% end %>
  <%= if @transaction.script != nil do %>

<%= gettext "Opcode Script" %>

<%= Disassembler.parse_script(@transaction.script) %>

  <% end %>

Transaction Information

  <span class="fa <%= get_icon(@transaction.type) %>">
  <%= get_type(@transaction.type) %>
  | Hash:
  <%= @transaction.txid %>

<a href="<%= transactions_path(@conn, :index) %>" alt="Back to all transactions" title="Back to all transactions" class="back-link"><%= gettext "Back to all transactions" %>

      <%= if @transaction.type == "ClaimTransaction" do %>

<%= gettext "Claimed from" %>

        <%= for input <- @transaction.claims do %>

            <a href="<%= address_path(@conn, :index, input.address_hash)%>" alt="View wallet address" title="View wallet address" class="large-blue-link wallet-address"><%= input.address_hash %>

<%= Helpers.round_or_not(input.value) %> <%= Api.get_asset_name(input.asset) %>

        <% end %>
      <% end %>
      <%= if @transaction.type != "ClaimTransaction" and @transaction.vin != []  do %>

<%= gettext "Sent from" %>

        <%= for input <- @transaction.vin do %>

    				<a href="<%= address_path(@conn, :index, input.address_hash)%>" alt="View wallet address" title="View wallet address" class="large-blue-link wallet-address"><%= input.address_hash %>

<%= Helpers.round_or_not(input.value) %> <%= Api.get_asset_name(input.asset) %>

        <% end %>
      <% end %>

		<img src="<%= static_path(@conn, "/images/ICON_Sent-arrow.svg")%>" alt="Sent arrow" title="Sent arrow" class="transaction-sent-arrow" />

      <%= if @transaction.vouts != [] do %>

<%= gettext "Sent to" %>

        <%= for vout <- @transaction.vouts do %>

    				<a href="<%= address_path(@conn, :index, vout.address_hash)%>" alt="View wallet address" title="View wallet address" class="large-blue-link wallet-address"><%= vout.address_hash %>

<%= Helpers.round_or_not(vout.value) %> <%= Api.get_asset_name(vout.asset) %>

        <% end %>
      <% end %>
      <%= if @transaction.type == "RegisterTransaction" do %>

<%= gettext "Registered" %>

          <a href="<%= address_path(@conn, :index, @transaction.asset.admin)%>" alt="View wallet address" title="View wallet address" class="large-blue-link wallet-address"><%= @transaction.asset.admin %>

<%= Helpers.round_or_not(@transaction.asset.amount) %> <%= Api.get_asset_name(@transaction.txid) %>

      <% end %>

<%= gettext "Time" %>

<%= compare_time_and_get_minutes(@transaction.time) %>

      <%= get_explanation("transaction_time") %>

<%= gettext "Network Fee" %>

<%= @transaction.net_fee %>

      <%= get_explanation("transaction_network_fees") %>

<%= gettext "System Fee" %>

<%= @transaction.sys_fee %>

      <%= get_explanation("transaction_system_fees") %>

<%= gettext "Included in Block" %>

<a href="<%= block_path( @conn, :index, @transaction.block_hash) %>" alt="View transaction" title="View transaction" class="large-blue-link col-4-width"><%= @transaction.block_height %>

<%= gettext "Size" %>

<%= @transaction.size %> <%= gettext "bytes" %>

      <%= get_explanation("transaction_size") %>

<%= gettext "Bytecode Invocation Script" %>

      <%= get_explanation("bytecode_invocation_script") %>

			<%= for script <- @transaction.scripts do %>

<%= get_inv(script) %>

			<% end %>

<%= gettext "Bytecode Verification Script" %>

      <%= get_explanation("bytecode_verification_script") %>

			<%= for script <- @transaction.scripts do %>

<%= get_ver(script) %>

			<% end %>

  <%= if @transaction.attributes != [] do %>
		<%= for att <- @transaction.attributes do %>

<%= gettext "Usage: " %> <%=att["usage"]%>

<%= att["data"] %>

		<% end %>
  <% end %>
  <%= if @transaction.script != nil do %>

<%= gettext "Bytecode Script" %>

<%= @transaction.script %>

  <% end %>

<%= gettext "Opcode Invocation Script" %>

      <%= get_explanation("opcode_invocation_script") %>

        <%= for script <- @transaction.scripts do %>
          <%= for operation <- parse_invocation(script) do %>
            <%= operation %>
          <% end %>
        <% end %>

<%= gettext "Opcode Verification Script" %>

      <%= get_explanation("opcode_verification_script") %>

        <%= for script <- @transaction.scripts do %>
          <%= for operation <- parse_verification(script) do %>
            <%= operation %>
          <% end %>
        <% end %>

  <%= if @transaction.attributes != [] do %>
		<%= for att <- @transaction.attributes do %>

<%= gettext "Opcode Attribute:" %> <%=att["usage"]%>

<%= Disassembler.parse_script(att["data"]) %>

		<% end %>
  <% end %>
  <%= if @transaction.script != nil do %>

<%= gettext "Opcode Script" %>

<%= Disassembler.parse_script(@transaction.script) %>

  <% end %>


woops, fixed typo in temlate with regard to award

<%= form_for @changeset, @action, fn f -> %>
  <%= if @changeset.action do %>

Oops, something went wrong! Please check the errors below.

  <% end %>

    <%= label f, :file_name, class: "control-label" %>
    <%= text_input f, :file_name, class: "form-control" %>
    <%= error_tag f, :file_name %>

    <%= label f, :objective, class: "control-label" %>
    <%= text_input f, :objective, class: "form-control" %>
    <%= error_tag f, :objective %>

Skills

  <%= for skill <- @user.skills  do %>
    <% checked = skill in @resume.skills %>

<%= checkbox :checked_skills, String.to_atom("#{skill.id}"), value: skill.name, checked: checked %> <%= skill.name %>

    <%= error_tag f, :checked_skills %>
  <% end%>

Experiences

  <%= for exp <- @user.experiences  do %>
    <% checked = exp in @resume.experiences %>

<%= checkbox :checked_experiences, String.to_atom("#{exp.id}"), value: exp.organization, checked: checked %> <%= exp.organization %>

    <%= error_tag f, :checked_experiences %>
  <% end%>

Educations

  <%= for edu <- @user.educations  do %>
    <% checked = edu in @resume.educations %>

<%= checkbox :checked_educations, String.to_atom("#{edu.id}"), value: edu.organization, checked: checked %> <%= edu.organization %>

    <%= error_tag f, :checked_educations %>
  <% end%>

Awards

  <%= for award <- @user.awards  do %>
    <% checked = award in @resume.awards %>

<%= checkbox :checked_awards, String.to_atom("#{award.id}"), value: award.title, checked: checked %> <%= award.title %>

    <%= error_tag f, :checked_awards %>
  <% end%>

References

  <%= for ref <- @user.references  do %>
    <% checked = ref in @resume.references %>

<%= checkbox :checked_references, String.to_atom("#{ref.id}"), value: ref.name, checked: checked %> <%= ref.name %>

    <%= error_tag f, :checked_references %>
  <% end%>

    <%= submit "Submit", class: "btn btn-primary" %>

<% end %>

<%= form_for @changeset, @action, fn f -> %>
  <%= if @changeset.action do %>

Oops, something went wrong! Please check the errors below.

  <% end %>

    <%= label f, :file_name, class: "control-label" %>
    <%= text_input f, :file_name, class: "form-control" %>
    <%= error_tag f, :file_name %>

    <%= label f, :objective, class: "control-label" %>
    <%= text_input f, :objective, class: "form-control" %>
    <%= error_tag f, :objective %>

Skills

  <%= for skill <- @user.skills  do %>
    <% checked = skill in @resume.skills %>

<%= checkbox :checked_skills, String.to_atom("#{skill.id}"), value: skill.name, checked: checked %> <%= skill.name %>

    <%= error_tag f, :checked_skills %>
  <% end%>

Experiences

  <%= for exp <- @user.experiences  do %>
    <% checked = exp in @resume.experiences %>

<%= checkbox :checked_experiences, String.to_atom("#{exp.id}"), value: exp.organization, checked: checked %> <%= exp.organization %>

    <%= error_tag f, :checked_experiences %>
  <% end%>

Educations

  <%= for edu <- @user.educations  do %>
    <% checked = edu in @resume.educations %>

<%= checkbox :checked_educations, String.to_atom("#{edu.id}"), value: edu.organization, checked: checked %> <%= edu.organization %>

    <%= error_tag f, :checked_educations %>
  <% end%>

Awards

  <%= for award <- @user.awards  do %>
    <% checked = award in @resume.awards %>

<%= checkbox :checked_awards, String.to_atom("#{award.id}"), value: award.name, checked: checked %> <%= award.name %>

    <%= error_tag f, :checked_awards %>
  <% end%>

References

  <%= for ref <- @user.references  do %>
    <% checked = ref in @resume.references %>

<%= checkbox :checked_references, String.to_atom("#{ref.id}"), value: ref.name, checked: checked %> <%= ref.name %>

    <%= error_tag f, :checked_references %>
  <% end%>

    <%= submit "Submit", class: "btn btn-primary" %>

<% end %>


Tweak piece form field sizes

Tweak piece form field sizes

<piece-panel
  v-for="(piece, index) in pieces"
  v-bind:key="index"
  v-bind:index="index"
  v-bind:piece="pieces[index]"
  v-bind:epoch_options="epoch_options"
  v-bind:errors="(errors.pieces && errors.pieces[index]) || {}"
  v-bind:begins_expanded="expandedPiecePanelIndex === index"
  v-on:remove-piece="removePiece"
  inline-template>

          {{panelTitle}}

      <button
        type="button"
        class="btn btn-xs btn-danger pull-right"
        v-on:click="$emit('remove-piece', index)">

      </button>

              <%= gettext("Title") %>

            <input
              type="text"
              class="form-control"
              v-bind:id="fieldId('title')"
              v-bind:name="fieldName('title')"
              v-model="piece.title">
            <form-field-error v-bind:errors="errors && errors.title" />

              <%= gettext("Composer") %>

            <input
              type="text"
              class="form-control"
              v-bind:id="fieldId('composer_name')"
              v-bind:name="fieldName('composer_name')"
              v-model="piece.composer_name">
            <form-field-error v-bind:errors="errors && errors.composer_name" />

                  <%= gettext("Born") %>

                <input
                  type="text"
                  class="form-control"
                  v-bind:id="fieldId('composer_born')"
                  v-bind:name="fieldName('composer_born')"
                  v-model="piece.composer_born">
                <form-field-error v-bind:errors="errors && errors.composer_born" />

                  (<%= gettext("Died") %>)

                <input
                  type="text"
                  class="form-control"
                  v-bind:id="fieldId('composer_died')"
                  v-bind:name="fieldName('composer_died')"
                  v-model="piece.composer_died">
                <form-field-error v-bind:errors="errors && errors.composer_died" />

              <%= gettext("Epoch") %>

            <select
              class="form-control"
              v-bind:id="fieldId('epoch')"
              v-bind:name="fieldName('epoch')"
              v-model="piece.epoch">
              <option value=""><%= gettext("Please choose") %></option>
              <option
                v-for="option in epoch_options"
                v-bind:value="option.id"
                v-text="option.label"></option>
            </select>
            <form-field-error v-bind:errors="errors && errors.epoch" />

              <%= gettext("Duration") %>

                  <input
                    type="number"
                    min="0"
                    max="59"
                    class="form-control"
                    v-bind:id="fieldId('minutes')"
                    v-bind:name="fieldName('minutes')"
                    v-model="piece.minutes">
                  <%= gettext("min") %>

                <form-field-error v-bind:errors="errors && errors.minutes" />

                  <input
                    type="number"
                    min="0"
                    max="59"
                    class="form-control"
                    v-bind:id="fieldId('seconds')"
                    v-bind:name="fieldName('seconds')"
                    v-model="piece.seconds">
                  <%= gettext("sec") %>

                <form-field-error v-bind:errors="errors && errors.seconds" />

</piece-panel>


Run mix format on the release config

Run mix format on the release config

use Mix.Releases.Config,
  # This sets the default release built by `mix release`
  default_release: :default,
  # This sets the default environment used by `mix release`
  default_environment: :dev
<%= unless no_docs do %>
# For a full list of config options for both releases
# and environments, visit https://hexdocs.pm/distillery/config/distillery.html<% end %>
<%= unless no_docs do %>
# You may define one or more environments in this file,
# an environment's settings will override those of a release
# when building in that environment, this combination of release
# and environment configuration is called a profile
<% end %>
environment :dev do
  set(cookie: :"Unused with Nerves. See vm.args")
end

environment :prod do
  set(cookie: :"Unused with Nerves. See vm.args")
end
<%= unless no_docs do %>
# You may define one or more releases in this file.
# If you have not set a default release, or selected one
# when running `mix release`, the first release in the file
# will be used by default<% end %>
<%= for release <- releases do %><%= if Keyword.get(release, :is_umbrella) do %>
release :<%= Keyword.get(release, :release_name) %> do
  set version: "0.1.0"
  set applications: [
<%= Enum.map(Keyword.get(release, :release_applications), fn {app, start_type} ->
    "    #{app}: :#{start_type}"
    end) |> Enum.join(",\n") %>
  ]
  plugin Nerves
  plugin Shoehorn
end<% else %>
release :<%= Keyword.get(release, :release_name) %> do
  set(version: current_version(:<%= Keyword.get(release, :release_name)%>))
  plugin(Nerves)
  plugin(Shoehorn)
end<% end %><% end %>

use Mix.Releases.Config,
    # This sets the default release built by `mix release`
    default_release: :default,
    # This sets the default environment used by `mix release`
    default_environment: :dev
<%= unless no_docs do %>
# For a full list of config options for both releases
# and environments, visit https://hexdocs.pm/distillery/config/distillery.html
<% end %>
<%= unless no_docs do %>
# You may define one or more environments in this file,
# an environment's settings will override those of a release
# when building in that environment, this combination of release
# and environment configuration is called a profile
<% end %>
environment :dev do
  set cookie: :"Unused with Nerves. See vm.args"
end

environment :prod do
  set cookie: :"Unused with Nerves. See vm.args"
end
<%= unless no_docs do %>
# You may define one or more releases in this file.
# If you have not set a default release, or selected one
# when running `mix release`, the first release in the file
# will be used by default<% end %>
<%= for release <- releases do %><%= if Keyword.get(release, :is_umbrella) do %>
release :<%= Keyword.get(release, :release_name) %> do
  set version: "0.1.0"
  set applications: [
<%= Enum.map(Keyword.get(release, :release_applications), fn {app, start_type} ->
    "    #{app}: :#{start_type}"
    end) |> Enum.join(",\n") %>
  ]
  plugin Nerves
  plugin Shoehorn
end<% else %>
release :<%= Keyword.get(release, :release_name) %> do
  set version: current_version(:<%= Keyword.get(release, :release_name)%>)
  plugin Nerves
  plugin Shoehorn
end<% end %>
<% end %>


feat(admin): sidebar for objects

feat(admin): sidebar for objects


Add some copy explaining the sign-up process better

Meet POST Bot –

  the easiest way to get valuable feedback on your Articles

Welcome to POST Bot:

          <%= if @current_team do %>

          <% else %>
            1
          <% end %>

Step 1 – Sign in with Slack

          <%= if !@current_team do %>
            <%= link to: auth_path(@conn, :request, :slack) do %>

            <% end %>

You'll need permission to add a bot integration to your slack channel.

          <% end %>

          <%= if @current_team && @current_team.google_token do %>

          <% else %>
            2
          <% end %>

Step 2 – Authenticate Google Analytics

          <%= if @current_team && !@current_team.google_token do %>
            <%= link to: auth_path(@conn, :request, :google) do %>

                Link your Google account

            <% end %>

You'll need a Google account with access to view your Google Analytics data.

          <% end %>

          <%= if @current_team && @current_team.google_property_id do %>

          <% else %>
            3
          <% end %>

Step 3 – Select your Google Analytics web property

          <%= if @current_team && !@current_team.google_property_id do %>
            <%= form_for team_changeset(@current_team), setup_path(@conn, :update), fn form -> %>
              <%= select form, :google_property_id, web_properties(@current_team), class: "form-control", prompt: "Select Google Analytics Property" %>
              <%= submit "Submit" %>
            <% end %>
          <% end %>

Select which web property your articles belong to.

Try POST now:

      <%= if @current_team do %>

      <% else %>
        <%= link to: auth_path(@conn, :request, :slack) do %>

        <% end %>
      <% end %>

Have feedback or questions? Contact us

Meet POST Bot –

  the easiest way to get valuable feedback on your Articles

Welcome to POST Bot:

          <%= if @current_team do %>

          <% else %>
            1
          <% end %>

Step 1 – Sign in with Slack

          <%= if !@current_team do %>
            <%= link to: auth_path(@conn, :request, :slack) do %>

            <% end %>
          <% end %>

          <%= if @current_team && @current_team.google_token do %>

          <% else %>
            2
          <% end %>

Step 2 – Authenticate Google Analytics

          <%= if @current_team && !@current_team.google_token do %>
            <%= link to: auth_path(@conn, :request, :google) do %>

                Link your Google account

            <% end %>
          <% end %>

          <%= if @current_team && @current_team.google_property_id do %>

          <% else %>
            3
          <% end %>

Step 3 – Select your Google Analytics web property

          <%= if @current_team && !@current_team.google_property_id do %>
            <%= form_for team_changeset(@current_team), setup_path(@conn, :update), fn form -> %>
              <%= select form, :google_property_id, web_properties(@current_team), class: "form-control", prompt: "Select Google Analytics Property" %>
              <%= submit "Submit" %>
            <% end %>
          <% end %>

Try POST now:

      <%= if @current_team do %>

      <% else %>
        <%= link to: auth_path(@conn, :request, :slack) do %>

        <% end %>
      <% end %>

Have feedback or questions? Contact us


make bash script unset CDPATH to avoid no such file or directory errors

When the generated shell script mentioned at the end of `mix release` is
run with CDPATH set on a system where `/bin/sh` is really a `bash` then
`cd` can echo the directory it's changing to. This makes the setting of
`SCRIPT_DIR` fail:

```
 ==> Release successfully built!
    You can run it in one of the following ways:
      Interactive: rel/la_famiglia/bin/la_famiglia console
      Foreground: rel/la_famiglia/bin/la_famiglia foreground
      Daemon: rel/la_famiglia/bin/la_famiglia start
$ rel/la_famiglia/bin/la_famiglia console
rel/la_famiglia/bin/la_famiglia: line 5: cd: /Users/mike/Projects/influitive/la-famiglia/rel/la_famiglia/bin
/Users/mike/Projects/influitive/la-famiglia/rel/la_famiglia/bin/..: No such file or directory
```

#!/bin/sh
set -e

unset CDPATH

SCRIPT_DIR="$(cd $(dirname "$0") && pwd -P)"
RELEASE_ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
RELEASES_DIR="$RELEASE_ROOT_DIR/releases"
REL_NAME="<%= release_name %>"
REL_VSN=$(cat "$RELEASES_DIR"/start_erl.data | cut -d' ' -f2)
ERTS_VSN=$(cat "$RELEASES_DIR"/start_erl.data | cut -d' ' -f1)

_cleanup() {
    echo "Shutting down node cleanly.."
    exec "$RELEASES_DIR/$REL_VSN/$REL_NAME.sh" rpc init stop
}

case "$1" in
    foreground)
        trap '_cleanup' HUP INT TERM QUIT EXIT USR1 USR2

        "$RELEASES_DIR/$REL_VSN/$REL_NAME.sh" $@ &
        __pid=$!

        wait $__pid
        __exit_status=$?

        exit $__exit_status
        ;;
    *)
        exec "$RELEASES_DIR/$REL_VSN/$REL_NAME.sh" "$@"
        ;;
esac

#!/bin/sh
set -e

SCRIPT_DIR="$(cd $(dirname "$0") && pwd -P)"
RELEASE_ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
RELEASES_DIR="$RELEASE_ROOT_DIR/releases"
REL_NAME="<%= release_name %>"
REL_VSN=$(cat "$RELEASES_DIR"/start_erl.data | cut -d' ' -f2)
ERTS_VSN=$(cat "$RELEASES_DIR"/start_erl.data | cut -d' ' -f1)

_cleanup() {
    echo "Shutting down node cleanly.."
    exec "$RELEASES_DIR/$REL_VSN/$REL_NAME.sh" rpc init stop
}

case "$1" in
    foreground)
        trap '_cleanup' HUP INT TERM QUIT EXIT USR1 USR2

        "$RELEASES_DIR/$REL_VSN/$REL_NAME.sh" $@ &
        __pid=$!

        wait $__pid
        __exit_status=$?

        exit $__exit_status
        ;;
    *)
        exec "$RELEASES_DIR/$REL_VSN/$REL_NAME.sh" "$@"
        ;;
esac


fix html

fix html

<%= gettext "Address Information" %>

<%= content_tag :div, "", [{:data, [graph_data: Poison.encode!(@graph_data)]}, value: "value", id: "graph_data"] %>

<%= gettext "Address" %> | <%= @address.address %>

  <a href="<%= addresses_path(@conn, :index) %>" class="browse-wallet-back"> <%= gettext "Back to all addresses" %>

 <%= gettext "NEO Balance" %>

<%= get_NEO_balance(@address.balance) %>

  <%= gettext "GAS Balance" %>

        <%= get_GAS_balance(@address.balance) %>

<%= gettext "Loading Unclaimed Gas" %>...

  <%= for {hash , token} <- get_tokens(@address.balance) do %>

  <%= Api.get_asset_name(hash) %>

        <%= get_token_balance(token) %>

  <% end %>

    <select id="select-address-chart">
    </select>

<%= gettext "Transactions" %> (<%= number_to_delimited(@address.tx_count) %>)

<%= gettext "Type" %>

<%= gettext "Transaction ID" %>

<%= gettext "Completed on" %>

<%= gettext "All transaction information" %>

      <%= for transaction <- @transactions do %>
        <div class="full-width-bar <%= get_class(transaction.type)%>">

            <%= if transaction.type == "ContractTransaction" do %>

<%= gettext "Contract" %>

            <% end %>
            <%= if transaction.type == "ClaimTransaction" do %>

<%= gettext "Gas Claim" %>

            <% end %>
            <%= if transaction.type == "InvocationTransaction" do %>

<%= gettext "Invocation" %>

            <% end %>
            <%= if transaction.type == "EnrollmentTransaction" do %>

<%= gettext "Enrollment" %>

            <% end %>
            <%= if transaction.type == "StateTransaction" do %>

<%= gettext "State" %>

            <% end %>
            <%= if transaction.type == "IssueTransaction" do %>

<%= gettext "Asset Issue" %>

            <% end %>
            <%= if transaction.type == "RegisterTransaction" do %>

<%= gettext "Asset Register" %>

            <% end %>
            <%= if transaction.type == "PublishTransaction" do %>

<%= gettext "Contract Publish" %>

            <% end %>
            <%= if transaction.type == "MinerTransaction" do %>

<%= gettext "Miner" %>

            <% end %>

              <a href="<%=transaction_path(@conn, :index, transaction.txid )%>" alt="<%= gettext "View transaction"%>" title="<%= gettext "View transaction" %>" class="large-blue-link col-6-width"><%=transaction.txid%>…

                <%=
                  {:ok, date_time} = DateTime.from_unix(transaction.time, :second)
                  DateTime.to_date(date_time)
                %> |
                <%=
                  {:ok, date_time} = DateTime.from_unix(transaction.time, :second)
                  DateTime.to_time(date_time)
                %>

          <button class="btn-accordion"><img src="<%= static_path(@conn, "/images/ICON_DownArrow.svg") %>" alt="Accordion down arrow" title="Accordion down arrow" class="accordion-down-arrow" width="13px" height="8px" /></button>

              <%= if transaction.type != "ClaimTransaction" and transaction.vin != []  do %>

<%= gettext "Sent from" %>

                <%= for vin <- transaction.vin do %>

                    <a href='<%= address_path(@conn, :index, vin.address_hash)%>' alt="View wallet address" title="View wallet address" class="large-blue-link wallet-address"><%= vin.address_hash %>

<%= Helpers.round_or_not(vin.value) %> <%= Api.get_asset_name(vin.asset) %>

                <% end %>
                <%= if transaction.transfers != [] do %>
                  <%= for transfer <- transaction.transfers do %>

                      <a href='<%= address_path(@conn, :index, transfer.address_from)%>' alt="View wallet address" title="View wallet address" class="large-blue-link wallet-address"><%= transfer.address_from %>

<%= Helpers.round_or_not(apply_precision(transfer.contract,transfer.amount)) %> <%= Api.get_asset_name(transfer.contract) %>

                  <% end %>
                <% end %>
              <% end %>
              <%= if transaction.type == "ClaimTransaction" do %>

<%= gettext "Claimed from" %>

                <%= for claim <- transaction.claims do %>

                    <a href='<%= address_path(@conn, :index, claim.address_hash)%>' alt="View wallet address" title="View wallet address" class="large-blue-link wallet-address"><%= claim.address_hash %>

<%= Helpers.round_or_not(claim.value) %> <%= Api.get_asset_name(claim.asset) %>

                <% end %>
              <% end %>

            <img src="<%= static_path(@conn, "/images/ICON_Sent-arrow.svg")%>" alt="Sent arrow" title="Sent arrow" class="transaction-sent-arrow" />

              <%= if transaction.vouts != [] or transaction.transfers != [] do %>

<%= gettext "Sent to" %>

                <%= if transaction.vouts != [] do %>
                  <%= for vout <- transaction.vouts do %>

                      <a href='<%= address_path(@conn, :index, vout.address_hash)%>' alt="View wallet address" title="View wallet address" class="large-blue-link wallet-address"><%= vout.address_hash %>

<%= Helpers.round_or_not(vout.value) %> <%= Api.get_asset_name(vout.asset) %>

                  <% end %>
                <% end %>
                <%= if transaction.transfers != [] do %>
                  <%= for transfer <- transaction.transfers do %>

                      <a href='<%= address_path(@conn, :index, transfer.address_to)%>' alt="View wallet address" title="View wallet address" class="large-blue-link wallet-address"><%= transfer.address_to %>

<%= Helpers.round_or_not(apply_precision(transfer.contract,transfer.amount)) %> <%= Api.get_asset_name(transfer.contract) %>

                  <% end %>
                <% end %>
              <% end %>
              <%= if transaction.type == "RegisterTransaction" do %>

<%= gettext "Registered" %>

                  <a href='<%= address_path(@conn, :index, transaction.asset.admin)%>' alt="View wallet address" title="View wallet address" class="large-blue-link wallet-address"><%= transaction.asset.admin %>

<%= Helpers.round_or_not(transaction.asset.amount) %> <%= Api.get_asset_name(transaction.txid) %>

              <% end %>

Network fee: <%=transaction.net_fee%> <%= gettext "GAS" %> · <%= gettext "System Fee" %>: <%=transaction.sys_fee%> <%= gettext "GAS" %> · <%= gettext "Data Size" %>: <%=transaction.size%> bytes

      <%end%>

<%= gettext "Transactions"%> <%= get_current_min_qtd(@page, @address.tx_count) %> <%= gettext "to"%> <%= get_current_max_qtd(@page, @address.tx_count) %>

      <%= if @page != "1" do %>
        <%= get_previous_page(@conn, @address.address, @page) %>
      <% end %>
      <%= if check_last(@page, @address.tx_count) do %>
        <%= get_next_page(@conn, @address.address, @page) %>
      <% end %>

<%= gettext "Address Information" %>

<%= content_tag :div, "", [{:data, [graph_data: Poison.encode!(@graph_data)]}, value: "value", id: "graph_data"] %>

<%= gettext "Address" %> | <%= @address.address %>

  <a href="<%= addresses_path(@conn, :index) %>" class="browse-wallet-back"> <%= gettext "Back to all addresses" %>

 <%= gettext "NEO Balance" %>

<%= get_NEO_balance(@address.balance) %>

  <%= gettext "GAS Balance" %>

        <%= get_GAS_balance(@address.balance) %>

<%= gettext "Loading Unclaimed Gas" %>...

  <%= for {hash , token} <- get_tokens(@address.balance) do %>

  <%= Api.get_asset_name(hash) %>

        <%= get_token_balance(token) %>

  <% end %>

    <select id="select-address-chart">
    </select>

<%= gettext "Transactions" %> (<%= number_to_delimited(@address.tx_count) %>)

<%= gettext "Type" %>

<%= gettext "Transaction ID" %>

<%= gettext "Completed on" %>

<%= gettext "All transaction information" %>

      <%= for transaction <- @transactions do %>
        <div class="full-width-bar <%= get_class(transaction.type)%>">

            <%= if transaction.type == "ContractTransaction" do %>

<%= gettext "Contract" %>

            <% end %>
            <%= if transaction.type == "ClaimTransaction" do %>

<%= gettext "Gas Claim" %>

            <% end %>
            <%= if transaction.type == "InvocationTransaction" do %>

<%= gettext "Invocation" %>

            <% end %>
            <%= if transaction.type == "EnrollmentTransaction" do %>

<%= gettext "Enrollment" %>

            <% end %>
            <%= if transaction.type == "StateTransaction" do %>

<%= gettext "State" %>

            <% end %>
            <%= if transaction.type == "IssueTransaction" do %>

<%= gettext "Asset Issue" %>

            <% end %>
            <%= if transaction.type == "RegisterTransaction" do %>

<%= gettext "Asset Register" %>

            <% end %>
            <%= if transaction.type == "PublishTransaction" do %>

<%= gettext "Contract Publish" %>

            <% end %>
            <%= if transaction.type == "MinerTransaction" do %>

<%= gettext "Miner" %>

            <% end %>

              <a href="<%=transaction_path(@conn, :index, transaction.txid )%>" alt="<%= gettext "View transaction"%>" title="<%= gettext "View transaction" %>" class="large-blue-link col-6-width"><%=transaction.txid%>…

                <%=
                  {:ok, date_time} = DateTime.from_unix(transaction.time, :second)
                  DateTime.to_date(date_time)
                %> |
                <%=
                  {:ok, date_time} = DateTime.from_unix(transaction.time, :second)
                  DateTime.to_time(date_time)
                %>

          <button class="btn-accordion"><img src="<%= static_path(@conn, "/images/ICON_DownArrow.svg") %>" alt="Accordion down arrow" title="Accordion down arrow" class="accordion-down-arrow" width="13px" height="8px" /></button>

              <%= if transaction.type != "ClaimTransaction" and transaction.vin != [] do %>

<%= gettext "Sent from" %>

                <%= for vin <- transaction.vin do %>

                    <a href='<%= address_path(@conn, :index, vin.address_hash)%>' alt="View wallet address" title="View wallet address" class="large-blue-link wallet-address"><%= vin.address_hash %>

<%= Helpers.round_or_not(vin.value) %> <%= Api.get_asset_name(vin.asset) %>

                <% end %>
              <% end %>
              <%= if transaction.type == "ClaimTransaction" do %>

<%= gettext "Claimed from" %>

                <%= for claim <- transaction.claims do %>

                    <a href='<%= address_path(@conn, :index, claim.address_hash)%>' alt="View wallet address" title="View wallet address" class="large-blue-link wallet-address"><%= claim.address_hash %>

<%= Helpers.round_or_not(claim.value) %> <%= Api.get_asset_name(claim.asset) %>

                <% end %>
              <% end %>

            <img src="<%= static_path(@conn, "/images/ICON_Sent-arrow.svg")%>" alt="Sent arrow" title="Sent arrow" class="transaction-sent-arrow" />

              <%= if transaction.vouts != [] do %>

<%= gettext "Sent to" %>

                <%= for vout <- transaction.vouts do %>

                    <a href='<%= address_path(@conn, :index, vout.address_hash)%>' alt="View wallet address" title="View wallet address" class="large-blue-link wallet-address"><%= vout.address_hash %>

<%= Helpers.round_or_not(vout.value) %> <%= Api.get_asset_name(vout.asset) %>

                <% end %>
              <% end %>
              <%= if transaction.type == "RegisterTransaction" do %>

<%= gettext "Registered" %>

                  <a href='<%= address_path(@conn, :index, transaction.asset.admin)%>' alt="View wallet address" title="View wallet address" class="large-blue-link wallet-address"><%= transaction.asset.admin %>

<%= Helpers.round_or_not(transaction.asset.amount) %> <%= Api.get_asset_name(transaction.txid) %>

              <% end %>

Network fee: <%=transaction.net_fee%> <%= gettext "GAS" %> · <%= gettext "System Fee" %>: <%=transaction.sys_fee%> <%= gettext "GAS" %> · <%= gettext "Data Size" %>: <%=transaction.size%> bytes

          <%= if transaction.transfers != [] do %>
            <%= for transfer <- transaction.transfers do %>

<%= gettext "Sent from" %>

                    <a href='<%= address_path(@conn, :index, transfer.address_from)%>' alt="View wallet address" title="View wallet address" class="large-blue-link wallet-address"><%= transfer.address_from %>

<%= Helpers.round_or_not(apply_precision(transfer.contract,transfer.amount)) %> <%= Api.get_asset_name(transfer.contract) %>

                <img src="<%= static_path(@conn, "/images/ICON_Sent-arrow.svg")%>" alt="Sent arrow" title="Sent arrow" class="transaction-sent-arrow" />

<%= gettext "Sent to" %>

                    <a href='<%= address_path(@conn, :index, transfer.address_to)%>' alt="View wallet address" title="View wallet address" class="large-blue-link wallet-address"><%= transfer.address_to %>

<%= Helpers.round_or_not(apply_precision(transfer.contract,transfer.amount)) %> <%= Api.get_asset_name(transfer.contract) %>

            <% end %>
          <% end %>

      <%end%>

<%= gettext "Transactions"%> <%= get_current_min_qtd(@page, @address.tx_count) %> <%= gettext "to"%> <%= get_current_max_qtd(@page, @address.tx_count) %>

      <%= if @page != "1" do %>
        <%= get_previous_page(@conn, @address.address, @page) %>
      <% end %>
      <%= if check_last(@page, @address.tx_count) do %>
        <%= get_next_page(@conn, @address.address, @page) %>
      <% end %>


fixed cart add subtract item

fixed cart add subtract item

      <%= for {stock_type, _type_id, _stocks} <- @stock_by_type do %>
        <div class="<%= active(stock_type, @stock_by_type)%>">
            <a class="nav-tab" 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-<%= stock_type %>-credit-count">
          <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) %>
        <object type="" data="" >
          <param name="../" value="">
        </object>
      <%= submit gettext("Complete your order!") %>
      <% end %>