Print timestamp in verbose logs for timing information

#!/usr/bin/env bash

set -e

# Set DEBUG_BOOT to output verbose debugging info during execution
if [ ! -z "$DEBUG_BOOT" ]; then
    export PS4='+\D{%s} '
    set -x
fi

# Name of the release
REL_NAME="${REL_NAME:-<%= release_name %>}"
# Current version of the release
REL_VSN="${REL_VSN:-<%= release_version %>}"
# Options passed to erl
ERL_OPTS="${ERL_OPTS:-<%= release.profile.erl_opts %>}"
# Environment variables for run_erl
RUN_ERL_ENV="${RUN_ERL_ENV:-<%= release.profile.run_erl_env %>}"
# Current version of ERTS being used
# If this is not present/unset, it will be detected
<%= if ((is_binary(include_erts) or include_erts) and not is_nil(erts_vsn)) do %>ERTS_VSN="${ERTS_VSN:-<%= erts_vsn %>}"<% end %>
DISTILLERY_VSN="<%= Application.spec(:distillery, :vsn) %>"
export REL_NAME
export REL_VSN
export ERL_OPTS
export RUN_ERL_ENV
export ERTS_VSN
export DISTILLERY_VSN

# If readlink has no -f option, or greadlink is not available,
# This function behaves like `readlink -f`
__bootstrap_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"
}

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

export ESCRIPT_NAME
ESCRIPT_NAME="${ESCRIPT_NAME:-$SCRIPT}"

# Parent directory of this script
SCRIPT_DIR="$(dirname "${SCRIPT}")"
# Root directory of all releases
RELEASE_ROOT_DIR="${RELEASE_ROOT_DIR:-$(dirname "$(dirname "${SCRIPT_DIR}")")}"
# The location of builtin command scripts
RELEASE_LIBEXEC_DIR="$SCRIPT_DIR/libexec"

# shellcheck source=../libexec/readlink.sh
. "$RELEASE_LIBEXEC_DIR/readlink.sh"
# shellcheck source=../libexec/logger.sh
. "$RELEASE_LIBEXEC_DIR/logger.sh"
# shellcheck source=../libexec/erts.sh
. "$RELEASE_LIBEXEC_DIR/erts.sh"
# shellcheck source=../libexec/helpers.sh
. "$RELEASE_LIBEXEC_DIR/helpers.sh"
# shellcheck source=../libexec/env.sh
. "$RELEASE_LIBEXEC_DIR/env.sh"
# shellcheck source=../libexec/config.sh
. "$RELEASE_LIBEXEC_DIR/config.sh"

# Make the release root our working directory
cd "$RELEASE_ROOT_DIR"

# We export this so that custom tasks in Elixir
# which need to know how they were invoked can
# check this environment variable.
export DISTILLERY_TASK="$1"

# All commands are loaded from the currently active release
COMMAND_DIR="$RELEASE_LIBEXEC_DIR/commands"
COMMAND_NAME="${1:-help}"
COMMAND_PATH="$COMMAND_DIR/$COMMAND_NAME.sh"

# Only shift if there is more than 0 args, or it will exit non-zero
if [ "$#" -ne 0 ]; then
   shift
fi

# Handle aliases
case $COMMAND_NAME in
    start|start_boot)
        configure_release
        . "$COMMAND_DIR/start.sh" "$COMMAND_NAME" "$@"
        ;;
    upgrade|downgrade|install)
        configure_release
        . "$COMMAND_DIR/install.sh" "$COMMAND_NAME" "$@"
        ;;
    console|console_clean|console_boot)
        configure_release
        . "$COMMAND_DIR/console.sh" "$COMMAND_NAME" "$@"
        ;;
    *)
        # If the command exists in libexec, execute
        # Otherwise check to see if it's the name of a custom command
        if [ -f "$COMMAND_PATH" ]; then
            configure_release
            . "$COMMAND_PATH" "$@"
        else
            COMMAND_PATH="$REL_DIR/commands/$COMMAND_NAME.sh"
            if [ -f "$COMMAND_PATH" ]; then
                configure_release
                require_cookie
                . "$COMMAND_PATH" "$@"
            else
                notice "'$COMMAND_NAME' is not a valid command"
                . "$COMMAND_DIR/help.sh"
            fi
        fi
        ;;
esac

#!/usr/bin/env bash

set -e

# Set DEBUG_BOOT to output verbose debugging info during execution
if [ ! -z "$DEBUG_BOOT" ]; then
    set -x
fi

# Name of the release
REL_NAME="${REL_NAME:-<%= release_name %>}"
# Current version of the release
REL_VSN="${REL_VSN:-<%= release_version %>}"
# Options passed to erl
ERL_OPTS="${ERL_OPTS:-<%= release.profile.erl_opts %>}"
# Environment variables for run_erl
RUN_ERL_ENV="${RUN_ERL_ENV:-<%= release.profile.run_erl_env %>}"
# Current version of ERTS being used
# If this is not present/unset, it will be detected
<%= if ((is_binary(include_erts) or include_erts) and not is_nil(erts_vsn)) do %>ERTS_VSN="${ERTS_VSN:-<%= erts_vsn %>}"<% end %>
DISTILLERY_VSN="<%= Application.spec(:distillery, :vsn) %>"
export REL_NAME
export REL_VSN
export ERL_OPTS
export RUN_ERL_ENV
export ERTS_VSN
export DISTILLERY_VSN

# If readlink has no -f option, or greadlink is not available,
# This function behaves like `readlink -f`
__bootstrap_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"
}

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

export ESCRIPT_NAME
ESCRIPT_NAME="${ESCRIPT_NAME:-$SCRIPT}"

# Parent directory of this script
SCRIPT_DIR="$(dirname "${SCRIPT}")"
# Root directory of all releases
RELEASE_ROOT_DIR="${RELEASE_ROOT_DIR:-$(dirname "$(dirname "${SCRIPT_DIR}")")}"
# The location of builtin command scripts
RELEASE_LIBEXEC_DIR="$SCRIPT_DIR/libexec"

# shellcheck source=../libexec/readlink.sh
. "$RELEASE_LIBEXEC_DIR/readlink.sh"
# shellcheck source=../libexec/logger.sh
. "$RELEASE_LIBEXEC_DIR/logger.sh"
# shellcheck source=../libexec/erts.sh
. "$RELEASE_LIBEXEC_DIR/erts.sh"
# shellcheck source=../libexec/helpers.sh
. "$RELEASE_LIBEXEC_DIR/helpers.sh"
# shellcheck source=../libexec/env.sh
. "$RELEASE_LIBEXEC_DIR/env.sh"
# shellcheck source=../libexec/config.sh
. "$RELEASE_LIBEXEC_DIR/config.sh"

# Make the release root our working directory
cd "$RELEASE_ROOT_DIR"

# We export this so that custom tasks in Elixir
# which need to know how they were invoked can
# check this environment variable.
export DISTILLERY_TASK="$1"

# All commands are loaded from the currently active release
COMMAND_DIR="$RELEASE_LIBEXEC_DIR/commands"
COMMAND_NAME="${1:-help}"
COMMAND_PATH="$COMMAND_DIR/$COMMAND_NAME.sh"

# Only shift if there is more than 0 args, or it will exit non-zero
if [ "$#" -ne 0 ]; then
   shift
fi

# Handle aliases
case $COMMAND_NAME in
    start|start_boot)
        configure_release
        . "$COMMAND_DIR/start.sh" "$COMMAND_NAME" "$@"
        ;;
    upgrade|downgrade|install)
        configure_release
        . "$COMMAND_DIR/install.sh" "$COMMAND_NAME" "$@"
        ;;
    console|console_clean|console_boot)
        configure_release
        . "$COMMAND_DIR/console.sh" "$COMMAND_NAME" "$@"
        ;;
    *)
        # If the command exists in libexec, execute
        # Otherwise check to see if it's the name of a custom command
        if [ -f "$COMMAND_PATH" ]; then
            configure_release
            . "$COMMAND_PATH" "$@"
        else
            COMMAND_PATH="$REL_DIR/commands/$COMMAND_NAME.sh"
            if [ -f "$COMMAND_PATH" ]; then
                configure_release
                require_cookie
                . "$COMMAND_PATH" "$@"
            else
                notice "'$COMMAND_NAME' is not a valid command"
                . "$COMMAND_DIR/help.sh"
            fi
        fi
        ;;
esac


Fixed user skill endorsement button bug

Fixed user skill endorsement button bug

Closes #334

  <%= for skill <- @user_skills do %>

        <%= link Skill.resolve_name(skill.skill_id), to: user_user_skill_path(@conn, :show, @user, skill) %>

          <%= if Enum.count(skill.endorsements) == 1 do %>
          <%= Enum.count(skill.endorsements) %> <%= gettext "upvote" %>
          <% end %>
          <%= if Enum.count(skill.endorsements) > 1 do %>
          <%= Enum.count(skill.endorsements) %> <%= gettext "upvotes" %>
          <% end %>

      <%= if @current_user do %>
        <%= if Vutuv.Endorsement.skill_endorsed?(skill.id, @current_user_id) do %>
          <%= button to: user_endorsement_path(@conn, :delete, @user, skill), method: :delete , class: "button button--icon", form: [class: "button button--icon"] do %>

          <% end %>
        <%= else %>
          <%= button to: user_endorsement_path(@conn, :create, @user, id: skill), method: :post , class: "button button--icon", form: [class: "button button--icon"] do %>

          <% end %>
        <%= end %>
        <%= if same_user?(@user, @current_user) do %>
        <%= button to: user_user_skill_path(@conn, :delete, @user, skill), method: :delete, class: "button button--icon", form: [class: "button button--icon"] do %>

        <% end %>
        <% end %>
      <% end %>

      <hr style="width: <%= (Enum.count(skill.endorsements)+1)/(Enum.count(hd(@user_skills).endorsements)+1)*100 %>%" />

  <% end %>

  <%= for skill <- @user_skills do %>

        <%= link Skill.resolve_name(skill.skill_id), to: user_user_skill_path(@conn, :show, @user, skill) %>

          <%= if Enum.count(skill.endorsements) == 1 do %>
          <%= Enum.count(skill.endorsements) %> <%= gettext "upvote" %>
          <% end %>
          <%= if Enum.count(skill.endorsements) > 1 do %>
          <%= Enum.count(skill.endorsements) %> <%= gettext "upvotes" %>
          <% end %>

      <%= if Vutuv.Endorsement.skill_endorsed?(skill.id, @conn.assigns[:current_user].id) do %>
        <%= button to: user_endorsement_path(@conn, :delete, @user, skill), method: :delete , class: "button button--icon", form: [class: "button button--icon"] do %>

        <% end %>
      <%= else %>
        <%= button to: user_endorsement_path(@conn, :create, @user, id: skill), method: :post , class: "button button--icon", form: [class: "button button--icon"] do %>

        <% end %>
      <%= end %>
      <%= if same_user?(@user, @current_user) do %>
      <%= button to: user_user_skill_path(@conn, :delete, @user, skill), method: :delete, class: "button button--icon", form: [class: "button button--icon"] do %>

      <% end %>
      <% end %>

      <hr style="width: <%= (Enum.count(skill.endorsements)+1)/(Enum.count(hd(@user_skills).endorsements)+1)*100 %>%" />

  <% end %>


Fix typo in posting.html

Fix typo in posting.html

<div class="post" data-posting-uid="<%= raw @posting.uid %>">

    <div class="image" style="background-image: url(<%= raw avatar_path(@posting.user) %>)">

<%= link sanitized_inline_markdown(@posting.title), to: permalink_posting_path(@conn, :show, @posting.permalink) %>

    <%= @posting.published_at |> human_readable_date %>

      by
      <a href="https://github.com/<%= raw @posting.user.user_name %>" target="_blank"> <%= raw @posting.user.user_name %>
      <%= if @posting.user.twitter_handle do %>
        /
        <a href="https://twitter.com/<%= raw @posting.user.twitter_handle %>" target="_blank"> <%= raw @posting.user.twitter_handle %>
      <% end %>

        <%= if @posting.published_tweet_uid do %>
          |
          <a href="https://twitter.com/intent/retweet?tweet_id=<%= @posting.published_tweet_uid %>" target="_blank"> Retweet this
        <% end %>

        <%= if @belongs_to_me? || admin?(@conn) do %>
          |
          <a href="<%= posting_path(@conn, :edit, @posting) %>"> Edit
        <% end %>

        <%= if admin?(@conn) do %>

            <a href="#" data-toggle="#unpublish-<%= @posting.uid %>">
            <span id="unpublish-<%= @posting.uid %>" style="display: none">
              <%= link "Unpublish", to: posting_path(@conn, :unpublish, @posting), method: :post %>

        <% end %>

    <%= sanitized_markdown @posting.text %>

  <%= if @just_created_by_me? && @posting.published_tweet_uid do %>

          <a href="https://twitter.com/<%= twitter_screen_name %>" target="_blank">@<%= twitter_screen_name %> just tweeted your post:

          <a class="btn btn-retweet" style="display: inline-block; float: right;" href="https://twitter.com/intent/retweet?tweet_id=<%= @posting.published_tweet_uid %>" target="_blank"> Retweet this!
          <%= raw ElixirStatus.Publisher.tweet_text(@posting, @posting.user.twitter_handle) %>

          Spread the word: If more people know about this site, more people will read your posts.

  <% end %>

<div class="post" data-posting-uid="<%= raw @posting.uid %>">

    <div class="image" style="background-image: url(<%= raw avatar_path(@posting.user) %>)">

<%= link sanitized_inline_markdown(@posting.title), to: permalink_posting_path(@conn, :show, @posting.permalink) %>

    <%= @posting.published_at |> human_readable_date %>

      by
      <a href="https://github.com/<%= raw @posting.user.user_name %>" target="_blank"> <%= raw @posting.user.user_name %>
      /
      <%= if @posting.user.twitter_handle do %>
        <a href="https://twitter.com/<%= raw @posting.user.twitter_handle %>" target="_blank"> <%= raw @posting.user.twitter_handle %>
      <% end %>

        <%= if @posting.published_tweet_uid do %>
          |
          <a href="https://twitter.com/intent/retweet?tweet_id=<%= @posting.published_tweet_uid %>" target="_blank"> Retweet this
        <% end %>

        <%= if @belongs_to_me? || admin?(@conn) do %>
          |
          <a href="<%= posting_path(@conn, :edit, @posting) %>"> Edit
        <% end %>

        <%= if admin?(@conn) do %>

            <a href="#" data-toggle="#unpublish-<%= @posting.uid %>">
            <span id="unpublish-<%= @posting.uid %>" style="display: none">
              <%= link "Unpublish", to: posting_path(@conn, :unpublish, @posting), method: :post %>

        <% end %>

    <%= sanitized_markdown @posting.text %>

  <%= if @just_created_by_me? && @posting.published_tweet_uid do %>

          <a href="https://twitter.com/<%= twitter_screen_name %>" target="_blank">@<%= twitter_screen_name %> just tweeted your post:

          <a class="btn btn-retweet" style="display: inline-block; float: right;" href="https://twitter.com/intent/retweet?tweet_id=<%= @posting.published_tweet_uid %>" target="_blank"> Retweet this!
          <%= raw ElixirStatus.Publisher.tweet_text(@posting, @posting.user.twitter_handle) %>

          Spread the word: If more people know about this site, more people will read your posts.

  <% end %>


Make Link to Edit Page dynamical

Make Link to Edit Page dynamical

Pages

<%= for page <- @pages do %>

    <%= link page.title, to: page.title %> - <%= link "[Edit]", to: page_path(@conn, :edit, page.title) %>

<% end %>

Pages

<%= for page <- @pages do %>

<%= link page.title, to: page.title %> - <%= link "[Edit]", to: page.title<>"/edit" %>

<% end %>


Tweak the footer position (#76)

Tweak the footer position (#76)

<!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>XEE.JP</title>
    <link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">
    <link rel="shortcut icon" href="<%= static_path(@conn, "/assets/favicon.ico") %>">

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.6/css/materialize.min.css">

実験管理画面

テーマ一覧

<%= link "ログアウト", to: session_path(@conn, :delete) %>

            XEE.JP

              <%= if logged_in?(@conn) do %>

<%= current_user(@conn).name %>

              <% else %>

<%= link "新規登録", to: registration_path(@conn, :new) %>

<%= link "ログイン", to: session_path(@conn, :new) %>

              <% end %>

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

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

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

© 2015 Ryohei HAYASHI All Rights Reserved.

Powered by Xee System.


Add version to layout footer

Add version to layout footer

<!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>Personal Twitter Bot</title>
    <link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">

Get Started

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

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

      <%= @inner %>

    Version <%= :application.get_key(:personal_twitter_bot, :vsn) |> elem(1) %>


Clarify in red that the selected user's name is a cancel operation.

      Player
      Chips
      Exact
      $1

    <%= for attendee_result <- @attendees do %>
      <% selected_player = (Integer.to_string(attendee_result.player_id) == @selected_player_id) %>

          <%= if selected_player && !@historical_game do %>
            <%= render("cash_out_player_button.html",
                  game_night_id: @game_night.id,
                  player_id: -1,
                  hostname: @hostname,
                  nickname: attendee_result.player.nickname,
                  classname: "btn-danger") %>
          <%= else %>
            <%= render("cash_out_player_button.html",
                  game_night_id: @game_night.id,
                  player_id: attendee_result.player_id,
                  hostname: @hostname,
                  nickname: attendee_result.player.nickname,
                  classname: "btn-default") %>
          <%= end %>

        <%= if selected_player && !@historical_game do %>

            <form
              class="form-search"
              style="margin: 0;"
              action="/attendee_result/<%= attendee_result.id %>/set_chipcount"
            >

              <input autofocus
                pattern="[0-9]*"
                type="text"
                name="chipcount"
                maxlength="7"
                size="7"
                value="<%= attendee_result.chips %>"
              />

              <input type="submit" value="OK" class="btn btn-primary">
            </form>

        <%= else %>

            <%= :erlang.float_to_binary(attendee_result.chips / 100, decimals: 2) %>

            <%= dollars_n_cents(attendee_result.exact_cents) %>

            $<%= round(attendee_result.rounded_cents / 100) %>

        <%= end %>

    <%= end %>

        TOTALS:

      <td class="<%= @chips_color %>">
        <%= :erlang.float_to_binary(@total_chips, decimals: 2) %>

        <%= dollars_n_cents(@exact_cents) %>

        $<%= round(@rounded_1_cents / 100) %>

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

    Please forward to:
    <%= Enum.join(@fwd_to, ", ") %>

<%= end %>

      Player
      Chips
      Exact
      $1

    <%= for attendee_result <- @attendees do %>
      <% selected_player = (Integer.to_string(attendee_result.player_id) == @selected_player_id) %>

          <%= if selected_player && !@historical_game do %>
            <%= render("cash_out_player_button.html",
                  game_night_id: @game_night.id,
                  player_id: -1,
                  hostname: @hostname,
                  nickname: attendee_result.player.nickname,
                  classname: "btn-primary") %>
          <%= else %>
            <%= render("cash_out_player_button.html",
                  game_night_id: @game_night.id,
                  player_id: attendee_result.player_id,
                  hostname: @hostname,
                  nickname: attendee_result.player.nickname,
                  classname: "btn-default") %>
          <%= end %>

        <%= if selected_player && !@historical_game do %>

            <form
              class="form-search"
              style="margin: 0;"
              action="/attendee_result/<%= attendee_result.id %>/set_chipcount"
            >

              <input autofocus
                pattern="[0-9]*"
                type="text"
                name="chipcount"
                maxlength="7"
                size="7"
                value="<%= attendee_result.chips %>"
              />

              <input type="submit" value="OK" class="btn btn-primary">
            </form>

        <%= else %>

            <%= :erlang.float_to_binary(attendee_result.chips / 100, decimals: 2) %>

            <%= dollars_n_cents(attendee_result.exact_cents) %>

            $<%= round(attendee_result.rounded_cents / 100) %>

        <%= end %>

    <%= end %>

        TOTALS:

      <td class="<%= @chips_color %>">
        <%= :erlang.float_to_binary(@total_chips, decimals: 2) %>

        <%= dollars_n_cents(@exact_cents) %>

        $<%= round(@rounded_1_cents / 100) %>

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

    Please forward to:
    <%= Enum.join(@fwd_to, ", ") %>

<%= end %>


remove unneeded classes

remove unneeded classes

Analytics

Users

total users: <%= length(@users) %>

      username
      age range
      postcode
      email
      Can send follow up email?
      delete

    <%= for u <- @users do %>

        <%= u.name %>
        <%= u.age_range %>
        <%= u.postcode %>

          <%= cond do %>
            <% u.email && u.email_consent -> %>
              <a href="mailto:<%= u.email %>"><%= u.email %>
            <% u.email -> %>
              <%= u.email %>
            <% true -> %>
              -----
          <% end %>

        <%= render_consent(u.email_consent) %>

          <%= link "X", to: user_path(@conn, :delete, u.id), method: "delete", class: "no-underline red" %>

    <% end %>


handle no votes case

handle no votes case

<div class="score-box" style="background-color: <%= score_color @poll.results.mean %>;">

		<%= if @poll.choice_type == "probability" do %>
			<%= round(@poll.results.mean * 100) %>%
		<% else %>
			<%= if @poll.results.mean do round(@poll.results.mean) else "?" end %>
		<% end %>

<%= @poll.results.total %> voting power

<div class="score-box" style="background-color: <%= score_color @poll.results.mean %>;">

		<%= if @poll.choice_type == "probability" do %>
			<%= round(@poll.results.mean * 100) %>%
		<% else %>
			<%= round(@poll.results.mean) %>
		<% end %>

<%= @poll.results.total %> voting power


Add code paths to erl when running command task. See #67

#!/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
<%= unless 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_HOOK="$REL_DIR/hooks/pre_start"
POST_START_HOOK="$REL_DIR/hooks/post_start"
PRE_STOP_HOOK="$REL_DIR/hooks/pre_stop"
POST_STOP_HOOK="$REL_DIR/hooks/post_stop"

# 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. For determining the version of ERTS available to the release
_detect_erts_vsn() {
    "$BINDIR/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_DIR" "$REL_NAME"
}

# 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
        __erl="$(which erl)"
        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" > "$2"
}

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

if [ $REPLACE_OS_VARS ]; then
    _replace_os_vars "$orig_vmargs_path" "$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
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

if [ $REPLACE_OS_VARS ]; then
    _replace_os_vars "$orig_sys_config_path" "$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
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")"
    else
        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
else
    # Extract cookie name from COOKIE_ARG
    COOKIE="$(echo "$COOKIE_ARG" | awk '{print $2}')"
fi

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

        [ -f "$PRE_START_HOOK" ] && . "$PRE_START_HOOK"

        # 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)"

        [ -f "$POST_START_HOOK" ] && . "$POST_START_HOOK"
        ;;

    stop)
        [ -f "$PRE_STOP_HOOK" ] && . "$PRE_STOP_HOOK"
        # 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
        [ -f "$POST_STOP_HOOK" ] && . "$POST_STOP_HOOK"
        ;;

    restart)
        [ -f "$PRE_START_HOOK" ] && . "$PRE_START_HOOK"
        ## Restart the VM without exiting the process
        if ! nodetool "restart"; then
            exit 1
        fi
        ;;

    reboot)
        [ -f "$PRE_START_HOOK" ] && . "$PRE_START_HOOK"
        ## Restart the VM completely (uses heart to restart it)
        if ! nodetool "reboot"; then
            exit 1
        fi
        ;;

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

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

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

    attach)
        # 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)
        # 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

        # 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/install_upgrade.escript" \
             "install" "$REL_NAME" "$NAME_TYPE" "$NAME" "$COOKIE" "$2"
        ;;

    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

        # 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/install_upgrade.escript" \
             "unpack" "$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"
                ;;
            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="$@"

        # 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
        [ -f "$PRE_START_HOOK" ] && . "$PRE_START_HOOK"

        __code_paths=$(_get_code_paths)
        # 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" \
            ${__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="$@"

        # Start the VM, executing pre and post start hooks
        [ -f "$PRE_START_HOOK" ] && . "$PRE_START_HOOK"

        # 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=$!
        [ -f "$POST_START_HOOK" ] && . "$POST_START_HOOK"
        wait $__bg_pid
        ;;
    rpc)
        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift

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

        shift

        nodetool rpcterms $@
        ;;
    eval)
        # 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)

        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 -- "$@" ${_code_paths}
        set -- "$@" -pa "$CONSOLIDATED_DIR"
        set -- "$@" -s "$MODULE" "$FUNCTION"

        $BINDIR/erlexec $@ -extra $ARGS
        exit "$?"
        ;;
    *)
        __command_path="$REL_DIR/commands/$1"
        if [ -f "$__command_path" ]; then
            . "$__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
<%= unless 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_HOOK="$REL_DIR/hooks/pre_start"
POST_START_HOOK="$REL_DIR/hooks/post_start"
PRE_STOP_HOOK="$REL_DIR/hooks/pre_stop"
POST_STOP_HOOK="$REL_DIR/hooks/post_stop"

# 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. For determining the version of ERTS available to the release
_detect_erts_vsn() {
    "$BINDIR/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_DIR" "$REL_NAME"
}

# 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
        __erl="$(which erl)"
        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" > "$2"
}

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

if [ $REPLACE_OS_VARS ]; then
    _replace_os_vars "$orig_vmargs_path" "$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
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

if [ $REPLACE_OS_VARS ]; then
    _replace_os_vars "$orig_sys_config_path" "$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
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")"
    else
        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
else
    # Extract cookie name from COOKIE_ARG
    COOKIE="$(echo "$COOKIE_ARG" | awk '{print $2}')"
fi

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

        [ -f "$PRE_START_HOOK" ] && . "$PRE_START_HOOK"

        # 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)"

        [ -f "$POST_START_HOOK" ] && . "$POST_START_HOOK"
        ;;

    stop)
        [ -f "$PRE_STOP_HOOK" ] && . "$PRE_STOP_HOOK"
        # 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
        [ -f "$POST_STOP_HOOK" ] && . "$POST_STOP_HOOK"
        ;;

    restart)
        [ -f "$PRE_START_HOOK" ] && . "$PRE_START_HOOK"
        ## Restart the VM without exiting the process
        if ! nodetool "restart"; then
            exit 1
        fi
        ;;

    reboot)
        [ -f "$PRE_START_HOOK" ] && . "$PRE_START_HOOK"
        ## Restart the VM completely (uses heart to restart it)
        if ! nodetool "reboot"; then
            exit 1
        fi
        ;;

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

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

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

    attach)
        # 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)
        # 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

        # 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/install_upgrade.escript" \
             "install" "$REL_NAME" "$NAME_TYPE" "$NAME" "$COOKIE" "$2"
        ;;

    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

        # 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/install_upgrade.escript" \
             "unpack" "$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"
                ;;
            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="$@"

        # 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
        [ -f "$PRE_START_HOOK" ] && . "$PRE_START_HOOK"

        __code_paths=$(_get_code_paths)
        # 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" \
            ${__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="$@"

        # Start the VM, executing pre and post start hooks
        [ -f "$PRE_START_HOOK" ] && . "$PRE_START_HOOK"

        # 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=$!
        [ -f "$POST_START_HOOK" ] && . "$POST_START_HOOK"
        wait $__bg_pid
        ;;
    rpc)
        # Make sure a node IS running
        if ! nodetool "ping" > /dev/null; then
            echo "Node is not running!"
            exit 1
        fi

        shift

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

        shift

        nodetool rpcterms $@
        ;;
    eval)
        # 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)

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

        # Save extra arguments
        ARGS="$@"

        # Build arguments for erlexec
        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 -- "$@" -s "$MODULE" "$FUNCTION"

        $BINDIR/erlexec $@ -extra $ARGS
        exit "$?"
        ;;
    *)
        __command_path="$REL_DIR/commands/$1"
        if [ -f "$__command_path" ]; then
            . "$__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