File elixir-1.11.4-git.patch of Package elixir
diff --git a/.github/workflows/builds.hex.pm.yml b/.github/workflows/builds.hex.pm.yml
new file mode 100644
index 000000000..f263f5a7c
--- /dev/null
+++ b/.github/workflows/builds.hex.pm.yml
@@ -0,0 +1,87 @@
+name: builds.hex.pm
+
+on:
+ push:
+ branches:
+ - main
+ - v*.*
+ tags:
+ - v*
+
+env:
+ ELIXIR_OPTS: "--warnings-as-errors"
+ ERLC_OPTS: "warnings_as_errors"
+ LANG: C.UTF-8
+
+concurrency: builds_txt
+
+jobs:
+ release_pre_built:
+ strategy:
+ fail-fast: true
+ max-parallel: 1
+ matrix:
+ include:
+ - otp: 23
+ otp_version: '23.3'
+ build_docs: build_docs
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ fetch-depth: 50
+ - name: Get tags
+ run: git fetch --tags origin
+ - uses: ./.github/workflows/release_pre_built
+ with:
+ otp_version: ${{ matrix.otp_version }}
+ otp: ${{ matrix.otp }}
+ build_docs: ${{ matrix.build_docs }}
+ - name: Utils.sh
+ run: |
+ cat << 'EOF' > utils.sh
+ function purge_key() {
+ curl \
+ -X POST \
+ -H "Fastly-Key: ${FASTLY_KEY}" \
+ -H "Accept: application/json" \
+ -H "Content-Length: 0" \
+ "https://api.fastly.com/service/$1/purge/$2"
+ }
+ function purge() {
+ purge_key ${FASTLY_REPO_SERVICE_ID} $1
+ purge_key ${FASTLY_BUILDS_SERVICE_ID} $1
+ sleep 2
+ purge_key ${FASTLY_REPO_SERVICE_ID} $1
+ purge_key ${FASTLY_BUILDS_SERVICE_ID} $1
+ sleep 2
+ purge_key ${FASTLY_REPO_SERVICE_ID} $1
+ purge_key ${FASTLY_BUILDS_SERVICE_ID} $1
+ }
+ EOF
+ chmod +x utils.sh
+ - name: Upload Docs to S3
+ if: ${{ matrix.build_docs }}
+ env:
+ AWS_ACCESS_KEY_ID: ${{ secrets.HEX_AWS_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.HEX_AWS_SECRET_ACCESS_KEY }}
+ AWS_REGION: ${{ secrets.HEX_AWS_REGION }}
+ AWS_S3_BUCKET: ${{ secrets.HEX_AWS_S3_BUCKET }}
+ FASTLY_REPO_SERVICE_ID: ${{ secrets.HEX_FASTLY_REPO_SERVICE_ID }}
+ FASTLY_BUILDS_SERVICE_ID: ${{ secrets.HEX_FASTLY_BUILDS_SERVICE_ID }}
+ FASTLY_KEY: ${{ secrets.HEX_FASTLY_KEY }}
+ run: |
+ source utils.sh
+ version=$(echo ${{ github.ref_name }} | sed -e 's/^v//g')
+ for f in doc/*; do
+ if [ -d "$f" ]; then
+ app=`echo $f | sed s/"doc\/"//`
+ tarball="${app}-${version}.tar.gz"
+ surrogate_key="docs/${app}-${version}"
+ tar -czf "${tarball}" -C "doc/${app}" .
+ aws s3 cp "${tarball}" "s3://${{ env.AWS_S3_BUCKET }}/docs/${tarball}" \
+ --cache-control "public,max-age=3600" \
+ --metadata "{\"surrogate-key\":\"${surrogate_key}\",\"surrogate-control\":\"public,max-age=604800\"}"
+ purge "${surrogate_key}"
+ fi
+ done
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f43a9ff62..a4bc8dbeb 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -15,7 +15,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- otp_release: ['OTP-23.0', 'OTP-22.3', 'OTP-22.0', 'OTP-21.3.8', 'OTP-21.0']
+ otp_release: ['OTP-24.0', 'OTP-23.0', 'OTP-22.3', 'OTP-22.0', 'OTP-21.3.8', 'OTP-21.0']
development: [false]
include:
- otp_release: master
diff --git a/.github/workflows/release_pre_built/action.yml b/.github/workflows/release_pre_built/action.yml
new file mode 100644
index 000000000..e8d063014
--- /dev/null
+++ b/.github/workflows/release_pre_built/action.yml
@@ -0,0 +1,51 @@
+name: "Release pre built"
+description: "Builds elixir release, ExDoc and generates docs"
+inputs:
+ otp:
+ description: "The major OTP version"
+ otp_version:
+ description: "The exact OTP version (major.minor[.patch])"
+ build_docs:
+ description: "If docs have to be built or not"
+runs:
+ using: "composite"
+ steps:
+ - uses: erlef/setup-beam@v1
+ with:
+ otp-version: ${{ inputs.otp_version }}
+ version-type: strict
+ - name: Build Elixir Release
+ shell: bash
+ run: |
+ make Precompiled.zip
+ mv Precompiled.zip elixir-otp-${{ inputs.otp }}.zip
+ shasum -a 1 elixir-otp-${{ inputs.otp }}.zip > elixir-otp-${{ inputs.otp }}.zip.sha1sum
+ shasum -a 256 elixir-otp-${{ inputs.otp }}.zip > elixir-otp-${{ inputs.otp }}.zip.sha256sum
+ echo "$PWD/bin" >> $GITHUB_PATH
+ - name: Get latest stable ExDoc version
+ if: ${{ inputs.build_docs }}
+ shell: bash
+ run: |
+ EX_DOC_LATEST_STABLE_VERSION=$(curl -s https://hex.pm/api/packages/ex_doc | jq --raw-output '.latest_stable_version')
+ echo "EX_DOC_LATEST_STABLE_VERSION=${EX_DOC_LATEST_STABLE_VERSION}" >> $GITHUB_ENV
+ - uses: actions/checkout@v3
+ if: ${{ inputs.build_docs }}
+ with:
+ repository: elixir-lang/ex_doc
+ ref: v${{ env.EX_DOC_LATEST_STABLE_VERSION }}
+ path: ex_doc
+ - name: Build ex_doc
+ if: ${{ inputs.build_docs }}
+ shell: bash
+ run: |
+ mv ex_doc ../ex_doc
+ cd ../ex_doc
+ ../elixir/bin/mix do local.rebar --force, local.hex --force, deps.get, compile
+ cd ../elixir
+ - name: Build Docs
+ if: ${{ inputs.build_docs }}
+ shell: bash
+ run: |
+ make Docs.zip
+ shasum -a 1 Docs.zip > Docs.zip.sha1sum
+ shasum -a 256 Docs.zip > Docs.zip.sha256sum
diff --git a/Makefile b/Makefile
index 68c44f8b9..93a565c19 100644
--- a/Makefile
+++ b/Makefile
@@ -178,40 +178,48 @@ clean_residual_files:
LOGO_PATH = $(shell test -f ../docs/logo.png && echo "--logo ../docs/logo.png")
SOURCE_REF = $(shell tag="$(call GIT_TAG)" revision="$(call GIT_REVISION)"; echo "$${tag:-$$revision}")
+
DOCS_FORMAT = html
-COMPILE_DOCS = bin/elixir ../ex_doc/bin/ex_doc "$(1)" "$(VERSION)" "lib/$(2)/ebin" --main "$(3)" --source-url "https://github.com/elixir-lang/elixir" --source-ref "$(call SOURCE_REF)" $(call LOGO_PATH) --output doc/$(2) --canonical "https://hexdocs.pm/$(2)/$(CANONICAL)" --homepage-url "https://elixir-lang.org/docs.html" --formatter "$(DOCS_FORMAT)" $(4)
+DOCS_COMPILE = CANONICAL=$(CANONICAL) bin/elixir ../ex_doc/bin/ex_doc "$(1)" "$(VERSION)" "lib/$(2)/ebin" --main "$(3)" --source-url "https://github.com/elixir-lang/elixir" --source-ref "$(call SOURCE_REF)" $(call LOGO_PATH) --output doc/$(2) --canonical "https://hexdocs.pm/$(2)/$(CANONICAL)" --homepage-url "https://elixir-lang.org/docs.html" --formatter "$(DOCS_FORMAT)" $(4)
+DOCS_CONFIG = bin/elixir lib/elixir/scripts/docs_config.exs "$(1)"
docs: compile ../ex_doc/bin/ex_doc docs_elixir docs_eex docs_mix docs_iex docs_ex_unit docs_logger
docs_elixir: compile ../ex_doc/bin/ex_doc
@ echo "==> ex_doc (elixir)"
$(Q) rm -rf doc/elixir
- $(call COMPILE_DOCS,Elixir,elixir,Kernel,--config "lib/elixir/docs.exs")
+ $(call DOCS_COMPILE,Elixir,elixir,Kernel,--config "lib/elixir/scripts/elixir_docs.exs")
+ $(call DOCS_CONFIG,elixir)
docs_eex: compile ../ex_doc/bin/ex_doc
@ echo "==> ex_doc (eex)"
$(Q) rm -rf doc/eex
- $(call COMPILE_DOCS,EEx,eex,EEx)
+ $(call DOCS_COMPILE,EEx,eex,EEx,--config "lib/elixir/scripts/mix_docs.exs")
+ $(call DOCS_CONFIG,eex)
docs_mix: compile ../ex_doc/bin/ex_doc
@ echo "==> ex_doc (mix)"
$(Q) rm -rf doc/mix
- $(call COMPILE_DOCS,Mix,mix,Mix)
+ $(call DOCS_COMPILE,Mix,mix,Mix,--config "lib/elixir/scripts/mix_docs.exs")
+ $(call DOCS_CONFIG,mix)
docs_iex: compile ../ex_doc/bin/ex_doc
@ echo "==> ex_doc (iex)"
$(Q) rm -rf doc/iex
- $(call COMPILE_DOCS,IEx,iex,IEx)
+ $(call DOCS_COMPILE,IEx,iex,IEx,--config "lib/elixir/scripts/mix_docs.exs")
+ $(call DOCS_CONFIG,iex)
docs_ex_unit: compile ../ex_doc/bin/ex_doc
@ echo "==> ex_doc (ex_unit)"
$(Q) rm -rf doc/ex_unit
- $(call COMPILE_DOCS,ExUnit,ex_unit,ExUnit)
+ $(call DOCS_COMPILE,ExUnit,ex_unit,ExUnit,--config "lib/elixir/scripts/mix_docs.exs")
+ $(call DOCS_CONFIG,ex_unit)
docs_logger: compile ../ex_doc/bin/ex_doc
@ echo "==> ex_doc (logger)"
$(Q) rm -rf doc/logger
- $(call COMPILE_DOCS,Logger,logger,Logger)
+ $(call DOCS_COMPILE,Logger,logger,Logger,--config "lib/elixir/scripts/mix_docs.exs")
+ $(call DOCS_CONFIG,logger)
../ex_doc/bin/ex_doc:
@ echo "ex_doc is not found in ../ex_doc as expected. See README for more information."
@@ -220,23 +228,23 @@ docs_logger: compile ../ex_doc/bin/ex_doc
#==> Zip tasks
Docs.zip: docs
- rm -f Docs-v$(VERSION).zip
- zip -9 -r Docs-v$(VERSION).zip CHANGELOG.md doc NOTICE LICENSE README.md
- @ echo "Docs file created $(CURDIR)/Docs-v$(VERSION).zip"
+ rm -f Docs.zip
+ zip -9 -r Docs.zip CHANGELOG.md doc NOTICE LICENSE README.md
+ @ echo "Docs file created $(CURDIR)/Docs.zip"
Precompiled.zip: build_man compile
- rm -f Precompiled-v$(VERSION).zip
- zip -9 -r Precompiled-v$(VERSION).zip bin CHANGELOG.md lib/*/ebin lib/*/lib LICENSE man NOTICE README.md VERSION
- @ echo "Precompiled file created $(CURDIR)/Precompiled-v$(VERSION).zip"
+ rm -f Precompiled.zip
+ zip -9 -r Precompiled.zip bin CHANGELOG.md lib/*/ebin lib/*/lib LICENSE man NOTICE README.md VERSION
+ @ echo "Precompiled file created $(CURDIR)/Precompiled.zip"
zips: Precompiled.zip Docs.zip
@ echo ""
@ echo "### Checksums"
@ echo ""
- @ shasum -a 1 < Precompiled-v$(VERSION).zip | sed -e "s/-//" | xargs echo " * Precompiled.zip SHA1:"
- @ shasum -a 512 < Precompiled-v$(VERSION).zip | sed -e "s/-//" | xargs echo " * Precompiled.zip SHA512:"
- @ shasum -a 1 < Docs-v$(VERSION).zip | sed -e "s/-//" | xargs echo " * Docs.zip SHA1:"
- @ shasum -a 512 < Docs-v$(VERSION).zip | sed -e "s/-//" | xargs echo " * Docs.zip SHA512:"
+ @ shasum -a 1 < Precompiled.zip | sed -e "s/-//" | xargs echo " * Precompiled.zip SHA1:"
+ @ shasum -a 512 < Precompiled.zip | sed -e "s/-//" | xargs echo " * Precompiled.zip SHA512:"
+ @ shasum -a 1 < Docs.zip | sed -e "s/-//" | xargs echo " * Docs.zip SHA1:"
+ @ shasum -a 512 < Docs.zip | sed -e "s/-//" | xargs echo " * Docs.zip SHA512:"
@ echo ""
#==> Test tasks
diff --git a/lib/elixir/scripts/docs_config.exs b/lib/elixir/scripts/docs_config.exs
new file mode 100644
index 000000000..e24101732
--- /dev/null
+++ b/lib/elixir/scripts/docs_config.exs
@@ -0,0 +1,19 @@
+# Generate docs_config.js for version chooser in ExDoc
+[app] = System.argv()
+
+{text_tags, 0} = System.cmd("git", ["tag"])
+skipped = Version.parse!("1.0.3")
+
+list_contents =
+ text_tags
+ |> String.split()
+ |> Enum.map(fn "v" <> rest -> Version.parse!(rest) end)
+ |> Enum.filter(&(Version.compare(&1, skipped) == :gt))
+ |> Enum.sort({:desc, Version})
+ |> Enum.map_intersperse(", ", fn version ->
+ version_string = to_string(version)
+ ~s[{"version":"v#{version_string}", "url":"https://hexdocs.pm/#{app}/#{version_string}"}]
+ end)
+
+File.mkdir_p!("doc/#{app}")
+File.write!("doc/#{app}/docs_config.js", ["var versionNodes = [", list_contents, "];\n"])
diff --git a/lib/elixir/docs.exs b/lib/elixir/scripts/elixir_docs.exs
similarity index 100%
rename from lib/elixir/docs.exs
rename to lib/elixir/scripts/elixir_docs.exs
diff --git a/lib/elixir/scripts/mix_docs.exs b/lib/elixir/scripts/mix_docs.exs
new file mode 100644
index 000000000..a5b76f55e
--- /dev/null
+++ b/lib/elixir/scripts/mix_docs.exs
@@ -0,0 +1,12 @@
+canonical = System.fetch_env!("CANONICAL")
+
+[
+ deps: [
+ eex: "https://hexdocs.pm/eex/#{canonical}",
+ elixir: "https://hexdocs.pm/elixir/#{canonical}",
+ ex_unit: "https://hexdocs.pm/ex_unit/#{canonical}",
+ iex: "https://hexdocs.pm/iex/#{canonical}",
+ logger: "https://hexdocs.pm/logger/#{canonical}",
+ mix: "https://hexdocs.pm/mix/#{canonical}"
+ ]
+]
diff --git a/lib/elixir/src/elixir_erl_compiler.erl b/lib/elixir/src/elixir_erl_compiler.erl
index 7010b59fd..e0aa05114 100644
--- a/lib/elixir/src/elixir_erl_compiler.erl
+++ b/lib/elixir/src/elixir_erl_compiler.erl
@@ -94,6 +94,8 @@ handle_file_warning(true, _File, {_Line, sys_core_fold, {nomatch_shadow, _}}) ->
%% Those we implement ourselves
handle_file_warning(_, _File, {_Line, v3_core, {map_key_repeated, _}}) -> ok;
+handle_file_warning(_, _File, {_Line, sys_core_fold, {ignored, useless_building}}) -> ok;
+%% TODO: remove when we require Erlang/OTP 24
handle_file_warning(_, _File, {_Line, sys_core_fold, useless_building}) -> ok;
%% Ignore all linting errors (only come up on parse transforms)
@@ -112,11 +114,11 @@ handle_file_error(File, {Line, Module, Desc}) ->
elixir_errors:compile_error([{line, Line}], File, Message).
%% Mention the capture operator in make_fun
-custom_format(sys_core_fold, {no_effect, {erlang, make_fun, 3}}) ->
+custom_format(sys_core_fold, {ignored, {no_effect, {erlang, make_fun, 3}}}) ->
"the result of the capture operator & (:erlang.make_fun/3) is never used";
%% Make no_effect clauses pretty
-custom_format(sys_core_fold, {no_effect, {erlang, F, A}}) ->
+custom_format(sys_core_fold, {ignored, {no_effect, {erlang, F, A}}}) ->
{Fmt, Args} = case erl_internal:comp_op(F, A) of
true -> {"use of operator ~ts has no effect", [elixir_utils:erlang_comparison_op_to_elixir(F)]};
false ->
@@ -127,12 +129,20 @@ custom_format(sys_core_fold, {no_effect, {erlang, F, A}}) ->
end,
io_lib:format(Fmt, Args);
-%% Rewrite nomatch_guard to be more generic it can happen inside if, unless, and the like
-custom_format(sys_core_fold, nomatch_guard) ->
+%% Rewrite nomatch to be more generic, it can happen inside if, unless, and the like
+custom_format(sys_core_fold, {nomatch, X}) when X == guard; X == no_clause ->
"this check/guard will always yield the same result";
+custom_format(sys_core_fold, {nomatch, {shadow, Line, {ErlName, ErlArity}}}) ->
+ {Name, Arity} = elixir_utils:erl_fa_to_elixir_fa(ErlName, ErlArity),
+
+ io_lib:format(
+ "this clause for ~ts/~B cannot match because a previous clause at line ~B always matches",
+ [Name, Arity, Line]
+ );
+
%% Handle literal eval failures
-custom_format(sys_core_fold, {eval_failure, {Mod, Name, Arity}, Error}) ->
+custom_format(sys_core_fold, {failed, {eval_failure, {Mod, Name, Arity}, Error}}) ->
#{'__struct__' := Struct} = 'Elixir.Exception':normalize(error, Error),
{ExMod, ExName, ExArgs} = elixir_rewrite:erl_to_ex(Mod, Name, lists:duplicate(Arity, nil)),
Call = 'Elixir.Exception':format_mfa(ExMod, ExName, length(ExArgs)),
@@ -143,18 +153,16 @@ custom_format(sys_core_fold, {eval_failure, {Mod, Name, Arity}, Error}) ->
["the call to ", Trimmed, " will fail with ", elixir_aliases:inspect(Struct)];
%% TODO: remove when we require OTP 24
+custom_format(sys_core_fold, {nomatch_shadow, Line, FA}) ->
+ custom_format(sys_core_fold, {nomatch, {shadow, Line, FA}});
+custom_format(sys_core_fold, nomatch_guard) ->
+ custom_format(sys_core_fold, {nomatch, guard});
+custom_format(sys_core_fold, {no_effect, X}) ->
+ custom_format(sys_core_fold, {ignored, {no_effect, X}});
custom_format(sys_core_fold, {eval_failure, Error}) ->
#{'__struct__' := Struct} = 'Elixir.Exception':normalize(error, Error),
["this expression will fail with ", elixir_aliases:inspect(Struct)];
-custom_format(sys_core_fold, {nomatch_shadow,Line,{ErlName,ErlArity}}) ->
- {Name, Arity} = elixir_utils:erl_fa_to_elixir_fa(ErlName, ErlArity),
-
- io_lib:format(
- "this clause for ~ts/~B cannot match because a previous clause at line ~B always matches",
- [Name, Arity, Line]
- );
-
custom_format([], Desc) ->
io_lib:format("~p", [Desc]);
diff --git a/lib/elixir/test/elixir/exception_test.exs b/lib/elixir/test/elixir/exception_test.exs
index df9d46bbc..ae08d5185 100644
--- a/lib/elixir/test/elixir/exception_test.exs
+++ b/lib/elixir/test/elixir/exception_test.exs
@@ -446,11 +446,12 @@ test "annotates undefined function error with suggestions" do
* min/1
"""
- assert blame_message(:erlang, & &1.gt_cookie()) == """
- function :erlang.gt_cookie/0 is undefined or private. Did you mean one of:
+ assert blame_message(:erlang, & &1.hal()) == """
+ function :erlang.hal/0 is undefined or private. Did you mean one of:
- * get_cookie/0
- * set_cookie/2
+ * halt/0
+ * halt/1
+ * halt/2
"""
end
diff --git a/lib/elixir/test/elixir/kernel/warning_test.exs b/lib/elixir/test/elixir/kernel/warning_test.exs
index 15a984a54..37334ff65 100644
--- a/lib/elixir/test/elixir/kernel/warning_test.exs
+++ b/lib/elixir/test/elixir/kernel/warning_test.exs
@@ -1154,31 +1154,6 @@ def foo(x), do: :ok
purge(Sample)
end
- test "with and do clauses emit errors, else clauses do not" do
- assert capture_err(fn ->
- Code.compile_string("""
- with {:first, int} when is_integer(int) <- {:second, Integer.gcd(2, 4)} do
- int
- end
- """)
- end) =~ "this clause cannot match"
-
- assert capture_err(fn ->
- Code.compile_string("""
- with {:first, int1} when is_integer(int1) <- {:first, Integer.gcd(2, 4)},
- {:second, int2} when is_integer(int2) <- {:second, Integer.gcd(2, 4)} do
- {:ok, int1 + int2}
- else
- {:first, nil} -> {:error, "first number is not integer"}
- {:second, nil} -> {:error, "second number is not integer"}
- end
- """)
- end) == ""
- after
- purge(Sample1)
- purge(Sample2)
- end
-
test "warning on code point escape" do
assert capture_err(fn ->
Code.eval_string("? ")
diff --git a/lib/logger/lib/logger/translator.ex b/lib/logger/lib/logger/translator.ex
index d1d7e62f1..8afd79436 100644
--- a/lib/logger/lib/logger/translator.ex
+++ b/lib/logger/lib/logger/translator.ex
@@ -357,15 +357,22 @@ defp child_info(_min_level, _child) do
[]
end
- defp child_debug(:debug, restart_type: restart, shutdown: shutdown, child_type: type) do
- ["\nRestart: ", inspect(restart), "\nShutdown: ", inspect(shutdown)] ++
- ["\nType: ", inspect(type)]
+ defp child_debug(:debug, opts) do
+ for {key, value} <- opts do
+ child_debug_key(key, value)
+ end
end
defp child_debug(_min_level, _child) do
[]
end
+ defp child_debug_key(:restart_type, value), do: ["\nRestart: " | inspect(value)]
+ defp child_debug_key(:shutdown, value), do: ["\nShutdown: " | inspect(value)]
+ defp child_debug_key(:child_type, value), do: ["\nType: " | inspect(value)]
+ defp child_debug_key(:significant, value), do: if(value, do: "\nSignificant: true", else: [])
+ defp child_debug_key(_, _), do: []
+
defp report_crash(min_level, [[{:initial_call, initial_call} | crashed], linked]) do
mfa = initial_call_to_mfa(initial_call)
report_crash(min_level, crashed, [{:initial_call, mfa}], linked)
diff --git a/lib/mix/lib/mix/task.ex b/lib/mix/lib/mix/task.ex
index af3db782d..11fc24bfd 100644
--- a/lib/mix/lib/mix/task.ex
+++ b/lib/mix/lib/mix/task.ex
@@ -387,15 +387,16 @@ defp run_task(proj, task, args) do
Mix.ProjectStack.on_recursing_root(fn -> run(task, args) end)
Mix.TasksServer.run({:task, task, proj}) ->
- if Mix.debug?(), do: output_task_debug_info(task, args, proj)
run_requirements(module)
- try do
- module.run(args)
- rescue
- e in OptionParser.ParseError ->
- Mix.raise("Could not invoke task #{inspect(task)}: " <> Exception.message(e))
- end
+ with_debug(task, args, proj, fn ->
+ try do
+ module.run(args)
+ rescue
+ e in OptionParser.ParseError ->
+ Mix.raise("Could not invoke task #{inspect(task)}: " <> Exception.message(e))
+ end
+ end)
true ->
:noop
@@ -409,8 +410,16 @@ defp run_requirements(module) do
end)
end
- defp output_task_debug_info(task, args, proj) do
- Mix.shell().info("** Running mix " <> task_to_string(task, args) <> project_to_string(proj))
+ defp with_debug(task, args, proj, fun) do
+ if Mix.debug?() do
+ shell = Mix.shell()
+ shell.info(["-> Running mix ", task_to_string(task, args), project_to_string(proj)])
+ {time, res} = :timer.tc(fun)
+ shell.info(["<- Ran mix ", task, " in ", Integer.to_string(div(time, 1000)), "ms"])
+ res
+ else
+ fun.()
+ end
end
defp project_to_string(nil), do: ""
diff --git a/lib/mix/test/mix/cli_test.exs b/lib/mix/test/mix/cli_test.exs
index 45857359e..80a2a5b9a 100644
--- a/lib/mix/test/mix/cli_test.exs
+++ b/lib/mix/test/mix/cli_test.exs
@@ -60,11 +60,11 @@ def run(_) do
assert contents =~ "This won't appear"
contents = mix(~w[my_hello], [{"MIX_DEBUG", "1"}])
- assert contents =~ "** Running mix my_hello (inside MyProject)"
+ assert contents =~ "-> Running mix my_hello (inside MyProject)"
assert contents =~ "** (Mix.Error) oops"
contents = mix(~w[my_hello], [{"MIX_DEBUG", "0"}])
- refute contents =~ "** Running mix my_hello (inside MyProject)"
+ refute contents =~ "-> Running mix my_hello (inside MyProject)"
refute contents =~ "** (Mix.Error) oops"
end)
end
diff --git a/lib/mix/test/mix/task_test.exs b/lib/mix/test/mix/task_test.exs
index ad59c32aa..5e11e9527 100644
--- a/lib/mix/test/mix/task_test.exs
+++ b/lib/mix/test/mix/task_test.exs
@@ -59,7 +59,8 @@ test "run/2 outputs task debug info if Mix.debug? is true" do
Mix.shell(Mix.Shell.IO)
Mix.debug(true)
- assert ExUnit.CaptureIO.capture_io(fn -> Mix.Task.run("hello") end) =~ "** Running mix hello"
+ assert ExUnit.CaptureIO.capture_io(fn -> Mix.Task.run("hello") end) =~
+ ~r"-> Running mix hello\n<- Ran mix hello in \d+ms"
after
Mix.shell(Mix.Shell.Process)
Mix.debug(false)