Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
c407d6d
Initial work on releases
Jan 22, 2019
7de863b
Tests for Mix.Release.from_config!
Jan 23, 2019
90205b5
More docs and tests
Jan 23, 2019
2b024e0
Remove proper erl.ini file
Jan 23, 2019
277ef4b
Cookie configuration
Jan 23, 2019
351aafc
Document hot code upgrades
Jan 23, 2019
9bfde19
generator_test.exs
Jan 24, 2019
9307be2
Do not copy OTP apps if include_erts is false
Jan 24, 2019
05c4bf6
Copyediting
Jan 24, 2019
c96dd35
Update lib/mix/lib/mix/release.ex
lukaszsamson Jan 24, 2019
bdfe36f
Apply suggestions from code review
lukaszsamson Jan 24, 2019
272ef08
Validate release names
Jan 24, 2019
f693d38
Fix docs
Jan 24, 2019
0580a19
Do not use string indexing in sh
Jan 24, 2019
b087c3e
Update lib/mix/lib/mix/tasks/release.ex
lukaszsamson Jan 24, 2019
ca47015
Keep exports together
Jan 24, 2019
f613d4c
Tests for copy_ebin
Jan 24, 2019
85838f5
More tests and refactoring
Jan 24, 2019
6c6382c
Phrasing
Jan 24, 2019
92d2f3c
Incorporate @bitwalker feedback
Jan 24, 2019
2940eef
More notes
Jan 24, 2019
b2fbb32
Update lib/mix/lib/mix/tasks/release.ex
wojtekmach Jan 25, 2019
68853f5
Add another TODO
Jan 25, 2019
a045cee
Raise if multiple releases and no default release
Jan 25, 2019
e73b7a3
Verify that the whole subtree is set to :none/:load
Jan 25, 2019
66429ce
Finish Mix.Release tests
Jan 25, 2019
3ee4dd9
Run the formatter
Jan 25, 2019
45c7cd4
Improvements under windows
Jan 25, 2019
26e5ced
Windows support
Jan 25, 2019
820272f
Handle symlinks when assembling a release
Jan 25, 2019
b686ab0
Update lib/mix/lib/mix/tasks/release.ex
wojtekmach Jan 25, 2019
91de895
Fixes for windows
Jan 25, 2019
d6ae4a1
Specify boot scripts upfront
Jan 27, 2019
9649ee0
Add tests for build_release_spec
Jan 27, 2019
676bcc9
Run the formatter
Jan 27, 2019
be8d2a5
Unit test boot script generation
Jan 27, 2019
1fcac1f
Unit tests for prepend paths
Jan 27, 2019
d187b97
Properly handle directories with spaces in releases
Jan 28, 2019
da3f54c
Smoke integration test
Jan 28, 2019
2dd6511
Run the formatter
Jan 28, 2019
53f6c81
More tests
Jan 28, 2019
3a1f78c
More tests
Jan 28, 2019
6d6f86c
Pending tests
Jan 28, 2019
210839b
Run the formatter
Jan 28, 2019
6f0c265
Execute sibling script directly
Jan 28, 2019
82a4546
Handle paths in Windows
Jan 28, 2019
d032465
More tests
Jan 28, 2019
b816487
Add HEART_COMMAND to bin/start instead, improve vm.args
Jan 28, 2019
c3ce4cf
Avoid more bashisms
Jan 28, 2019
8a0ebd5
Fixes on Windows
Jan 28, 2019
e241bb7
More docs and fixes
Jan 28, 2019
e288bce
Remove race on daemon mode, fix windows path
Jan 28, 2019
bf7bd5e
More windows path fixes
Jan 28, 2019
30a20a0
Increase timeout value
Jan 28, 2019
750cee2
Wait until file contents are written
Jan 28, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 56 additions & 32 deletions bin/elixir
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,6 @@ The following options are generally used under releases.
It will attempt to create PIPEDIR and LOGDIR if they don't exist.
See run_erl to learn more. To reattach, run: to_erl PIPEDIR.

--pipe-to automatically sets \$HEART_COMMAND if none is set.
See the -heart mode of the Erlang VM for more information.

** Options marked with (*) can be given more than once." >&2
exit 1
fi
Expand All @@ -67,11 +64,20 @@ readlink_f () {
fi
}

MODE="elixir"
ERL_EXEC="erl"
# Stores static erlang arguments and --erl (which is passed as is)
ERL=""

# Stores erl arguments preserving spaces/quotes (mimics an array)
erl () {
eval "E$E=\$1"
E=$(($E + 1))
}

MODE="elixir"
I=1
E=0
LENGTH=$#
set -- "$@" -extra

while [ $I -le $LENGTH ]; do
S=1
Expand Down Expand Up @@ -102,59 +108,66 @@ while [ $I -le $LENGTH ]; do
--hidden)
ERL="$ERL -hidden"
;;
--cookie)
S=2
ERL="$ERL -setcookie "$2""
;;
--sname|--name)
S=2
ERL="$ERL $(echo $1 | cut -c 2-) "$2""
;;
--logger-otp-reports)
S=2
if [ "$2" = 'true' ] || [ "$2" = 'false' ]; then
ERL="$ERL -logger handle_otp_reports "$2""
ERL="$ERL -logger handle_otp_reports $2"
fi
;;
--logger-sasl-reports)
S=2
if [ "$2" = 'true' ] || [ "$2" = 'false' ]; then
ERL="$ERL -logger handle_sasl_reports "$2""
ERL="$ERL -logger handle_sasl_reports $2"
fi
;;
--erl)
S=2
ERL="$ERL "$2""
ERL="$ERL $2"
;;
--cookie)
S=2
erl "-setcookie"
erl "$2"
;;
--sname|--name)
S=2
erl $(echo $1 | cut -c 2-)
erl "$2"
;;
--erl-config)
S=2
ERL="$ERL -config "$2""
erl "-config"
erl "$2"
;;
--vm-args)
S=2
ERL="$ERL -args_file "$2""
erl "-args_file"
erl "$2"
;;
--boot)
S=2
ERL="$ERL -boot "$2""
erl "-boot"
erl "$2"
;;
--boot-var)
S=3
ERL="$ERL -boot_var "$2" "$3""
erl "-boot_var"
erl "$2"
erl "$3"
;;
--pipe-to)
S=3
RUN_ERL_PIPE="$2"
if [[ "$RUN_ERL_PIPE" == "-"* ]]; then
echo "--pipe-to : PIPEDIR cannot be a switch" >&2
exit 1
fi
case "$RUN_ERL_PIPE" in
-*) echo "--pipe-to : PIPEDIR cannot be a switch" >&2 && exit 1;;
*);;
esac

RUN_ERL_LOG="$3"
if [[ "$RUN_ERL_LOG" == "-"* ]]; then
echo "--pipe-to : LOGDIR cannot be a switch" >&2
exit 1
fi
case "$RUN_ERL_LOG" in
-*) echo "--pipe-to : LOGDIR cannot be a switch" >&2 && exit 1;;
*);;
esac
;;
--werl)
USE_WERL=true
Expand All @@ -173,9 +186,16 @@ while [ $I -le $LENGTH ]; do
shift $S
done

I=$(($E - 1))
while [ $I -ge 0 ]; do
eval "VAL=\$E$I"
set -- "$VAL" "$@"
I=$(($I - 1))
done

SELF=$(readlink_f "$0")
SCRIPT_PATH=$(dirname "$SELF")
ERTS_BIN=""
ERL_EXEC="erl"

if [ "$OSTYPE" = "cygwin" ]; then SCRIPT_PATH=$(cygpath -m "$SCRIPT_PATH"); fi
if [ "$MODE" != "iex" ]; then ERL="-noshell -s elixir start_cli $ERL"; fi
Expand All @@ -186,14 +206,18 @@ else
if [ $USE_WERL ]; then ERL_EXEC="werl"; fi
fi

set -- "$ERTS_BIN$ERL_EXEC" -pa "$SCRIPT_PATH"/../lib/*/ebin $ELIXIR_ERL_OPTIONS $ERL -extra "$@"
ERTS_BIN=""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ERTS_BIN is not doing anything in this script, as it will always be ""

set -- "$ERTS_BIN$ERL_EXEC" -pa "$SCRIPT_PATH"/../lib/*/ebin $ELIXIR_ERL_OPTIONS $ERL "$@"

if [ -n "$RUN_ERL_PIPE" ]; then
ESCAPED=""
for PART in "$@"; do
ESCAPED=""$ESCAPED" $(echo "$PART" | sed 's/[^a-zA-Z0-9_\-\/]/\\&/g')"
done
mkdir -p "$RUN_ERL_PIPE"
mkdir -p "$RUN_ERL_LOG"
ERL_EXEC="run_erl"
set -- "$ERTS_BIN$ERL_EXEC" -daemon "$RUN_ERL_PIPE/" "$RUN_ERL_LOG/" "$(printf "%q " "$@")"
export HEART_COMMAND=${HEART_COMMAND:-$(printf "%q " "$@")}
set -- "$ERTS_BIN$ERL_EXEC" -daemon "$RUN_ERL_PIPE/" "$RUN_ERL_LOG/" "$ESCAPED"
fi

exec "$@"
2 changes: 1 addition & 1 deletion bin/iex.bat
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@if defined ELIXIR_CLI_ECHO (@echo on) else (@echo off)
@if defined ELIXIR_CLI_ECHO (@echo on) else (@echo off)
setlocal
if /I ""%1""==""--help"" goto documentation
if /I ""%1""==""-h"" goto documentation
Expand Down
78 changes: 67 additions & 11 deletions lib/mix/lib/mix/generator.ex
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
defmodule Mix.Generator do
@moduledoc """
Conveniences for working with paths and generating content.

All of these functions are verbose, in the sense they log
the action to be performed via `Mix.shell/0`.
"""

@doc ~S"""
Creates a file with the given contents.
If the file already exists, asks for user confirmation.

If the file already exists and the contents are not the same,
it asks for user confirmation.

## Options

* `:force` - forces installation without a shell prompt.
* `:force` - forces installation without a shell prompt
* `:quiet` - do not log command output

## Examples

Expand All @@ -21,13 +21,16 @@ defmodule Mix.Generator do
:ok

"""
@spec create_file(Path.t(), iodata, keyword) :: any
@spec create_file(Path.t(), iodata, keyword) :: boolean()
def create_file(path, contents, opts \\ []) when is_binary(path) do
Mix.shell().info([:green, "* creating ", :reset, Path.relative_to_cwd(path)])
log(:green, :creating, Path.relative_to_cwd(path), opts)

if opts[:force] || Mix.Utils.can_write?(path) do
if opts[:force] || overwrite?(path, contents) do
File.mkdir_p!(Path.dirname(path))
File.write!(path, contents)
true
else
false
end
end

Expand All @@ -37,17 +40,70 @@ defmodule Mix.Generator do
This function does nothing if the given directory already exists; in this
case, it still logs the directory creation.

## Options

* `:quiet` - do not log command output

## Examples

iex> Mix.Generator.create_directory("path/to/dir")
* creating path/to/dir
:ok

"""
@spec create_directory(Path.t()) :: any
def create_directory(path) when is_binary(path) do
Mix.shell().info([:green, "* creating ", :reset, Path.relative_to_cwd(path)])
@spec create_directory(Path.t(), keyword) :: true
def create_directory(path, options \\ []) when is_binary(path) do
log(:green, "creating", Path.relative_to_cwd(path), options)
File.mkdir_p!(path)
true
end

@doc """
Prompts the user to overwrite the file if it exists.

Returns false if the file exists and the user forbade
to override it. Returns true otherwise.
"""
@doc since: "1.9.0"
@spec overwrite?(Path.t(), iodata) :: boolean
def overwrite?(path) do
if File.exists?(path) do
full = Path.expand(path)
Mix.shell().yes?(Path.relative_to_cwd(full) <> " already exists, overwrite?")
else
true
end
end

@doc """
Prompts the user to overwrite the file if it exists.

The contents are compared to avoid asking the user to
override if the contents did not change. Returns false
if the file exists and the content is the same or the
user forbade to override it. Returns true otherwise.
"""
@doc since: "1.9.0"
@spec overwrite?(Path.t(), iodata) :: boolean
def overwrite?(path, contents) do
case File.read(path) do
{:ok, binary} ->
if binary == IO.iodata_to_binary(contents) do
false
else
full = Path.expand(path)
Mix.shell().yes?(Path.relative_to_cwd(full) <> " already exists, overwrite?")
end

_ ->
true
end
end

defp log(color, command, message, opts) do
unless opts[:quiet] do
Mix.shell().info([color, "* #{command} ", :reset, message])
end
end

@doc """
Expand Down
Loading