Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9fd85b06dc | ||
|
|
ec81110b3e | ||
|
|
094a76d514 | ||
|
|
7d737bc5ec | ||
|
|
3eb074282a | ||
|
|
b8732bd248 | ||
|
|
2252a8ff55 | ||
|
|
9a9cf419a1 | ||
|
|
0f92512030 | ||
|
|
e0806f9d6c | ||
|
|
5db9d55926 | ||
|
|
3cb3d41368 | ||
|
|
a3a081c949 | ||
|
|
207350fb44 | ||
|
|
6f7a68c9e3 | ||
|
|
0936fb45d5 | ||
|
|
bccfca4ffe | ||
|
|
417255fe1b |
@@ -30,7 +30,7 @@ jobs:
|
|||||||
- otp: 26
|
- otp: 26
|
||||||
otp_version: '26.0'
|
otp_version: '26.0'
|
||||||
build_docs: build_docs
|
build_docs: build_docs
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ permissions:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
create_draft_release:
|
create_draft_release:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
steps:
|
steps:
|
||||||
@@ -40,7 +40,7 @@ jobs:
|
|||||||
- otp: 26
|
- otp: 26
|
||||||
otp_version: '26.0'
|
otp_version: '26.0'
|
||||||
build_docs: build_docs
|
build_docs: build_docs
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
@@ -56,7 +56,9 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
gh release upload --clobber "${{ github.ref_name }}" \
|
gh release upload --clobber "${{ github.ref_name }}" \
|
||||||
elixir-otp-${{ matrix.otp }}.zip \
|
elixir-otp-${{ matrix.otp }}.zip \
|
||||||
elixir-otp-${{ matrix.otp }}.zip.sha{1,256}sum
|
elixir-otp-${{ matrix.otp }}.zip.sha{1,256}sum \
|
||||||
|
elixir-otp-${{ matrix.otp }}.exe \
|
||||||
|
elixir-otp-${{ matrix.otp }}.exe.sha{1,256}sum
|
||||||
- name: Upload Docs to GitHub
|
- name: Upload Docs to GitHub
|
||||||
if: ${{ matrix.build_docs }}
|
if: ${{ matrix.build_docs }}
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -22,6 +22,20 @@ runs:
|
|||||||
shasum -a 1 elixir-otp-${{ inputs.otp }}.zip > elixir-otp-${{ inputs.otp }}.zip.sha1sum
|
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
|
shasum -a 256 elixir-otp-${{ inputs.otp }}.zip > elixir-otp-${{ inputs.otp }}.zip.sha256sum
|
||||||
echo "$PWD/bin" >> $GITHUB_PATH
|
echo "$PWD/bin" >> $GITHUB_PATH
|
||||||
|
- name: Install NSIS
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y nsis
|
||||||
|
- name: Build Elixir Windows Installer
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
export OTP_VERSION=${{ inputs.otp_version }}
|
||||||
|
export ELIXIR_ZIP=$PWD/elixir-otp-${{ inputs.otp }}.zip
|
||||||
|
(cd lib/elixir/scripts/windows_installer && ./build.sh)
|
||||||
|
mv lib/elixir/scripts/windows_installer/tmp/elixir-otp-${{ inputs.otp }}.exe .
|
||||||
|
shasum -a 1 elixir-otp-${{ inputs.otp }}.exe > elixir-otp-${{ inputs.otp }}.exe.sha1sum
|
||||||
|
shasum -a 256 elixir-otp-${{ inputs.otp }}.exe > elixir-otp-${{ inputs.otp }}.exe.sha256sum
|
||||||
- name: Get latest stable ExDoc version
|
- name: Get latest stable ExDoc version
|
||||||
if: ${{ inputs.build_docs }}
|
if: ${{ inputs.build_docs }}
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
+19
-50
@@ -68,7 +68,7 @@ In Elixir v1.15, the new reports will look like:
|
|||||||
error: undefined function foo/0 (there is no such import)
|
error: undefined function foo/0 (there is no such import)
|
||||||
my_file.exs:1
|
my_file.exs:1
|
||||||
|
|
||||||
** (CompileError) nofile: cannot compile file (errors have been logged)
|
** (CompileError) my_file.exs: cannot compile file (errors have been logged)
|
||||||
|
|
||||||
A new function, called `Code.with_diagnostics/2`, has been added so this
|
A new function, called `Code.with_diagnostics/2`, has been added so this
|
||||||
information can be leveraged by editors, allowing them to point to several
|
information can be leveraged by editors, allowing them to point to several
|
||||||
@@ -100,61 +100,16 @@ config :logger, :default_formatter,
|
|||||||
format: "$time $message $metadata"
|
format: "$time $message $metadata"
|
||||||
```
|
```
|
||||||
|
|
||||||
If you use `Logger.Backends.Console` or other backends, they are
|
If you use `Logger.Backends.Console` with a custom device or other
|
||||||
still fully supported and functional. If you implement your own
|
backends, they are still fully supported and functional. If you
|
||||||
backends, you want to consider migrating to
|
implement your own backends, you want to consider migrating to
|
||||||
[`:logger_backends`](https://github.com/elixir-lang/logger_backends)
|
[`:logger_backends`](https://github.com/elixir-lang/logger_backends)
|
||||||
in the long term.
|
in the long term.
|
||||||
|
|
||||||
See the new `Logger` documentation for more information on the
|
See the new `Logger` documentation for more information on the
|
||||||
new features and on compatibility.
|
new features and on compatibility.
|
||||||
|
|
||||||
## v1.15.0-rc.1 (2022-05-29)
|
## v1.15.0 (2023-06-19)
|
||||||
|
|
||||||
### 1. Enhancements
|
|
||||||
|
|
||||||
#### Elixir
|
|
||||||
|
|
||||||
* [File] Support distributed `File.Stream`
|
|
||||||
* [Module] Add `Module.get_last_attribute/3`
|
|
||||||
* [Task] Reduce footprint of tasks by avoiding unecessary work during spawning
|
|
||||||
|
|
||||||
#### ExUnit
|
|
||||||
|
|
||||||
* [ExUnit.Case] Add `ExUnit.Case.get_last_registered_test/1`
|
|
||||||
|
|
||||||
### 2. Bug fixes
|
|
||||||
|
|
||||||
#### Elixir
|
|
||||||
|
|
||||||
* [Code] Ensure `:on_undefined_variable` option works as advertised (regression)
|
|
||||||
* [Code] Format paths in `Code.with_diagnostic/2` as relative paths (regression)
|
|
||||||
* [Kernel] Raise when macros are given to dialyzer
|
|
||||||
* [Kernel] Support bitstring specifiers as map keys in pattern (regression)
|
|
||||||
* [Module] Ensure that `Module.get_attribute/3` returns `nil` and not the given default value when an attribute has been explicitly set as `nil`
|
|
||||||
* [Task] Do not double log Task failure reports
|
|
||||||
|
|
||||||
#### ExUnit
|
|
||||||
|
|
||||||
* [ExUnit.CaptureLog] Allow capturing deprecated log level (regression)
|
|
||||||
* [ExUnit.DocTest] Ensure proper line is returned when failing to parse doctest results
|
|
||||||
|
|
||||||
#### IEx
|
|
||||||
|
|
||||||
* [IEx] Fix IO operations not returning when booting IEx (regression)
|
|
||||||
|
|
||||||
#### Mix
|
|
||||||
|
|
||||||
* [mix deps] Ensure dependencies with `included_applications` can be loaded (regression)
|
|
||||||
* [mix format] Ensure proper formatter options are returned for files (regression)
|
|
||||||
|
|
||||||
### 3. Soft deprecations
|
|
||||||
|
|
||||||
#### Elixir
|
|
||||||
|
|
||||||
* [Kernel] Require pin variable when accessing variable inside binary size in match
|
|
||||||
|
|
||||||
## v1.15.0-rc.0 (2022-05-22)
|
|
||||||
|
|
||||||
### 1. Enhancements
|
### 1. Enhancements
|
||||||
|
|
||||||
@@ -175,6 +130,7 @@ new features and on compatibility.
|
|||||||
* [Date] Add `Date.before?/2` and `Date.after?/2`
|
* [Date] Add `Date.before?/2` and `Date.after?/2`
|
||||||
* [DateTime] Add `DateTime.before?/2` and `DateTime.after?/2`
|
* [DateTime] Add `DateTime.before?/2` and `DateTime.after?/2`
|
||||||
* [DateTime] Support precision in `DateTime.utc_now/2`
|
* [DateTime] Support precision in `DateTime.utc_now/2`
|
||||||
|
* [File] Support distributed `File.Stream`
|
||||||
* [Inspect] `Inspect` now renders `'charlists'` as `~c"charlists"` by default
|
* [Inspect] `Inspect` now renders `'charlists'` as `~c"charlists"` by default
|
||||||
* [Kernel] Break down `case` and `cond` inside `dbg/2`
|
* [Kernel] Break down `case` and `cond` inside `dbg/2`
|
||||||
* [Kernel] Add `t:nonempty_binary/0` and `t:nonempty_bitstring/0`
|
* [Kernel] Add `t:nonempty_binary/0` and `t:nonempty_bitstring/0`
|
||||||
@@ -195,6 +151,8 @@ new features and on compatibility.
|
|||||||
* [NaiveDateTime] Add `NaiveDateTime.beginning_of_day/1` and `NaiveDateTime.end_of_day/1`
|
* [NaiveDateTime] Add `NaiveDateTime.beginning_of_day/1` and `NaiveDateTime.end_of_day/1`
|
||||||
* [NaiveDateTime] Add `NaiveDateTime.before?/2` and `NaiveDateTime.after?/2`
|
* [NaiveDateTime] Add `NaiveDateTime.before?/2` and `NaiveDateTime.after?/2`
|
||||||
* [NaiveDateTime] Support precision in `NaiveDateTime.utc_now/2`
|
* [NaiveDateTime] Support precision in `NaiveDateTime.utc_now/2`
|
||||||
|
* [Module] Mark functions as generated in "Docs" chunk
|
||||||
|
* [Module] Add `Module.get_last_attribute/3`
|
||||||
* [OptionParser] Support `:return_separator` option
|
* [OptionParser] Support `:return_separator` option
|
||||||
* [Process] Add `Process.alias/0,1` and `Process.unalias/1`
|
* [Process] Add `Process.alias/0,1` and `Process.unalias/1`
|
||||||
* [Range] Add `Range.split/2`
|
* [Range] Add `Range.split/2`
|
||||||
@@ -204,6 +162,7 @@ new features and on compatibility.
|
|||||||
* [System] Support `:lines` in `System.cmd/3` to capture output line by line
|
* [System] Support `:lines` in `System.cmd/3` to capture output line by line
|
||||||
* [Task] Remove head of line blocking on `Task.yield_many/2`
|
* [Task] Remove head of line blocking on `Task.yield_many/2`
|
||||||
* [Task] Enable selective receive optimizations in Erlang/OTP 26+
|
* [Task] Enable selective receive optimizations in Erlang/OTP 26+
|
||||||
|
* [Task] Reduce tasks footprint by avoiding unecessary work during spawning
|
||||||
* [Task.Supervisor] Do not copy args on temporary `Task.Supervisor.start_child/2`
|
* [Task.Supervisor] Do not copy args on temporary `Task.Supervisor.start_child/2`
|
||||||
* [Time] Add `Time.before?/2` and `Time.after?/2`
|
* [Time] Add `Time.before?/2` and `Time.after?/2`
|
||||||
* [URI] Add `URI.append_path/2`
|
* [URI] Add `URI.append_path/2`
|
||||||
@@ -212,7 +171,9 @@ new features and on compatibility.
|
|||||||
|
|
||||||
* [ExUnit] Add more color configuration to ExUnit CLI formatter
|
* [ExUnit] Add more color configuration to ExUnit CLI formatter
|
||||||
* [ExUnit.Callbacks] Accept `{module, function}` tuples in ExUnit `setup` callbacks
|
* [ExUnit.Callbacks] Accept `{module, function}` tuples in ExUnit `setup` callbacks
|
||||||
|
* [ExUnit.Case] Add `ExUnit.Case.get_last_registered_test/1`
|
||||||
* [ExUnit.Doctest] Add `ExUnit.DocTest.doctest_file/2`
|
* [ExUnit.Doctest] Add `ExUnit.DocTest.doctest_file/2`
|
||||||
|
* [ExUnit.Doctest] Include `doctest_data` in doctest tags
|
||||||
* [ExUnit.Formatter] When comparing two anonymous functions, defined at the same place but capturing a different environment, we will now also diff the environments
|
* [ExUnit.Formatter] When comparing two anonymous functions, defined at the same place but capturing a different environment, we will now also diff the environments
|
||||||
|
|
||||||
#### IEx
|
#### IEx
|
||||||
@@ -267,16 +228,22 @@ new features and on compatibility.
|
|||||||
* [Kernel] Expand macros on the left side of -> in `try/rescue`
|
* [Kernel] Expand macros on the left side of -> in `try/rescue`
|
||||||
* [Kernel] Raise on misplaced `...` inside typespecs
|
* [Kernel] Raise on misplaced `...` inside typespecs
|
||||||
* [Kernel] Do not import `behaviour_info` and `module_info` functions from Erlang modules
|
* [Kernel] Do not import `behaviour_info` and `module_info` functions from Erlang modules
|
||||||
|
* [Kernel] Raise when macros are given to dialyzer
|
||||||
* [Kernel.ParallelCompiler] Make sure compiler doesn't crash when there are stray messages in the inbox
|
* [Kernel.ParallelCompiler] Make sure compiler doesn't crash when there are stray messages in the inbox
|
||||||
* [Kernel.ParallelCompiler] Track compile and runtime warnings separately
|
* [Kernel.ParallelCompiler] Track compile and runtime warnings separately
|
||||||
|
* [Module] Ensure that `Module.get_attribute/3` returns `nil` and not the given default value when an attribute has been explicitly set as `nil`
|
||||||
* [System] Fix race condition when a script would terminate before `System.stop/1` executes
|
* [System] Fix race condition when a script would terminate before `System.stop/1` executes
|
||||||
|
* [Task] Do not double log Task failure reports
|
||||||
* [URI] Make sure `URI.merge/2` works accordingly with relative paths
|
* [URI] Make sure `URI.merge/2` works accordingly with relative paths
|
||||||
|
|
||||||
#### ExUnit
|
#### ExUnit
|
||||||
|
|
||||||
* [ExUnit] Fix crash when `@tag capture_log: true` was set to true and the Logger application was shut down in the middle of the test
|
* [ExUnit] Fix crash when `@tag capture_log: true` was set to true and the Logger application was shut down in the middle of the test
|
||||||
* [ExUnit] Do not merge context as tags inside the runner to reduce memory usage when emitting events to formatters
|
* [ExUnit] Do not merge context as tags inside the runner to reduce memory usage when emitting events to formatters
|
||||||
|
* [ExUnit] Mark test cases as invalid when an exit occurs during `setup_all`
|
||||||
* [ExUnit] Do not expand or collect vars from quote in ExUnit assertions
|
* [ExUnit] Do not expand or collect vars from quote in ExUnit assertions
|
||||||
|
* [ExUnit.DocTest] Ensure proper line is returned when failing to parse doctest results
|
||||||
|
* [ExUnit.Doctest] Fix line information when a doctest with multiple assertions fails
|
||||||
|
|
||||||
#### IEx
|
#### IEx
|
||||||
|
|
||||||
@@ -288,6 +255,7 @@ new features and on compatibility.
|
|||||||
|
|
||||||
* [mix compile] Include `cwd` in compiler cache key
|
* [mix compile] Include `cwd` in compiler cache key
|
||||||
* [mix release] Fix Windows service when invoking `erlsrv.exe` in path with spaces
|
* [mix release] Fix Windows service when invoking `erlsrv.exe` in path with spaces
|
||||||
|
* [mix xref] Raise early if `mix xref` is used at the umbrella root
|
||||||
|
|
||||||
### 3. Soft deprecations (no warnings emitted)
|
### 3. Soft deprecations (no warnings emitted)
|
||||||
|
|
||||||
@@ -295,6 +263,7 @@ new features and on compatibility.
|
|||||||
|
|
||||||
* [File] `File.cp/3` and `File.cp_r/3` with a function as third argument
|
* [File] `File.cp/3` and `File.cp_r/3` with a function as third argument
|
||||||
is deprecated in favor of a keyword list
|
is deprecated in favor of a keyword list
|
||||||
|
* [Kernel] Require pin variable when accessing variable inside binary size in match
|
||||||
* [Kernel.ParallelCompiler] Require the `:return_diagnostics` option to be
|
* [Kernel.ParallelCompiler] Require the `:return_diagnostics` option to be
|
||||||
set to true when compiling or requiring code
|
set to true when compiling or requiring code
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ PREFIX ?= /usr/local
|
|||||||
TEST_FILES ?= "*_test.exs"
|
TEST_FILES ?= "*_test.exs"
|
||||||
SHARE_PREFIX ?= $(PREFIX)/share
|
SHARE_PREFIX ?= $(PREFIX)/share
|
||||||
MAN_PREFIX ?= $(SHARE_PREFIX)/man
|
MAN_PREFIX ?= $(SHARE_PREFIX)/man
|
||||||
#CANONICAL := MAJOR.MINOR/
|
CANONICAL := 1.15/
|
||||||
CANONICAL ?= main/
|
CANONICAL ?= main/
|
||||||
DOCS_FORMAT ?= html
|
DOCS_FORMAT ?= html
|
||||||
ELIXIRC := bin/elixirc --ignore-module-conflict $(ELIXIRC_OPTS)
|
ELIXIRC := bin/elixirc --ignore-module-conflict $(ELIXIRC_OPTS)
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
6. Copy the relevant bits from /CHANGELOG.md to the GitHub release and publish it
|
6. Copy the relevant bits from /CHANGELOG.md to the GitHub release and publish it
|
||||||
|
|
||||||
7. Add the release to `elixir.csv` with the minimum supported OTP version (all releases), update `erlang.csv` to the latest supported OTP version, and `_data/elixir-versions.yml` (except for RCs) files in `elixir-lang/elixir-lang.github.com`
|
7. Update `_data/elixir-versions.yml` (except for RCs) in `elixir-lang/elixir-lang.github.com`
|
||||||
|
|
||||||
## Creating a new vMAJOR.MINOR branch (after first rc)
|
## Creating a new vMAJOR.MINOR branch (after first rc)
|
||||||
|
|
||||||
|
|||||||
+2
-3
@@ -6,12 +6,11 @@ Elixir applies bug fixes only to the latest minor branch. Security patches are a
|
|||||||
|
|
||||||
Elixir version | Support
|
Elixir version | Support
|
||||||
:------------- | :-----------------------------
|
:------------- | :-----------------------------
|
||||||
1.15 | Development
|
1.15 | Bug fixes and security patches
|
||||||
1.14 | Bug fixes and security patches
|
1.14 | Security patches only
|
||||||
1.13 | Security patches only
|
1.13 | Security patches only
|
||||||
1.12 | Security patches only
|
1.12 | Security patches only
|
||||||
1.11 | Security patches only
|
1.11 | Security patches only
|
||||||
1.10 | Security patches only
|
|
||||||
|
|
||||||
## Announcements
|
## Announcements
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
ELIXIR_VERSION=1.15.0-rc.1
|
ELIXIR_VERSION=1.15.0
|
||||||
|
|
||||||
if [ $# -eq 0 ] || { [ $# -eq 1 ] && { [ "$1" = "--help" ] || [ "$1" = "-h" ]; }; }; then
|
if [ $# -eq 0 ] || { [ $# -eq 1 ] && { [ "$1" = "--help" ] || [ "$1" = "-h" ]; }; }; then
|
||||||
cat <<USAGE >&2
|
cat <<USAGE >&2
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
@if defined ELIXIR_CLI_ECHO (@echo on) else (@echo off)
|
@if defined ELIXIR_CLI_ECHO (@echo on) else (@echo off)
|
||||||
|
|
||||||
set ELIXIR_VERSION=1.15.0-rc.1
|
set ELIXIR_VERSION=1.15.0
|
||||||
|
|
||||||
setlocal enabledelayedexpansion
|
setlocal enabledelayedexpansion
|
||||||
if ""%1""=="""" if ""%2""=="""" goto documentation
|
if ""%1""=="""" if ""%2""=="""" goto documentation
|
||||||
|
|||||||
@@ -3,10 +3,6 @@ defmodule Code.Fragment do
|
|||||||
This module provides conveniences for analyzing fragments of
|
This module provides conveniences for analyzing fragments of
|
||||||
textual code and extract available information whenever possible.
|
textual code and extract available information whenever possible.
|
||||||
|
|
||||||
Most of the functions in this module provide a best-effort
|
|
||||||
and may not be accurate under all circumstances. Read each
|
|
||||||
documentation for more information.
|
|
||||||
|
|
||||||
This module should be considered experimental.
|
This module should be considered experimental.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -3009,13 +3009,16 @@ defmodule Enum do
|
|||||||
|
|
||||||
if first < count and amount > 0 do
|
if first < count and amount > 0 do
|
||||||
amount = Kernel.min(amount, count - first)
|
amount = Kernel.min(amount, count - first)
|
||||||
amount = if step == 1, do: amount, else: div(amount - 1, step) + 1
|
amount = amount_with_step(amount, step)
|
||||||
fun.(first, amount, step)
|
fun.(first, amount, step)
|
||||||
else
|
else
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp amount_with_step(amount, 1), do: amount
|
||||||
|
defp amount_with_step(amount, step), do: div(amount - 1, step) + 1
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Returns a subset list of the given `enumerable`, from `start_index` (zero-based)
|
Returns a subset list of the given `enumerable`, from `start_index` (zero-based)
|
||||||
with `amount` number of elements if available.
|
with `amount` number of elements if available.
|
||||||
@@ -4440,7 +4443,7 @@ defmodule Enum do
|
|||||||
|
|
||||||
if start >= 0 do
|
if start >= 0 do
|
||||||
amount = Kernel.min(amount, count - start)
|
amount = Kernel.min(amount, count - start)
|
||||||
amount = if step == 1, do: amount, else: div(amount - 1, step) + 1
|
amount = amount_with_step(amount, step)
|
||||||
fun.(start, amount, step)
|
fun.(start, amount, step)
|
||||||
else
|
else
|
||||||
[]
|
[]
|
||||||
@@ -4448,7 +4451,7 @@ defmodule Enum do
|
|||||||
end
|
end
|
||||||
|
|
||||||
defp slice_forward(list, start, amount, step) when is_list(list) do
|
defp slice_forward(list, start, amount, step) when is_list(list) do
|
||||||
amount = if step == 1, do: amount, else: div(amount - 1, step) + 1
|
amount = amount_with_step(amount, step)
|
||||||
slice_list(list, start, amount, step)
|
slice_list(list, start, amount, step)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -4458,7 +4461,7 @@ defmodule Enum do
|
|||||||
[]
|
[]
|
||||||
|
|
||||||
{:ok, count, fun} when is_function(fun, 1) ->
|
{:ok, count, fun} when is_function(fun, 1) ->
|
||||||
amount = Kernel.min(amount, count - start)
|
amount = Kernel.min(amount, count - start) |> amount_with_step(step)
|
||||||
enumerable |> fun.() |> slice_exact(start, amount, step, count)
|
enumerable |> fun.() |> slice_exact(start, amount, step, count)
|
||||||
|
|
||||||
# TODO: Deprecate me in Elixir v1.18.
|
# TODO: Deprecate me in Elixir v1.18.
|
||||||
@@ -4473,8 +4476,7 @@ defmodule Enum do
|
|||||||
end
|
end
|
||||||
|
|
||||||
{:ok, count, fun} when is_function(fun, 3) ->
|
{:ok, count, fun} when is_function(fun, 3) ->
|
||||||
amount = Kernel.min(amount, count - start)
|
amount = Kernel.min(amount, count - start) |> amount_with_step(step)
|
||||||
amount = if step == 1, do: amount, else: div(amount - 1, step) + 1
|
|
||||||
fun.(start, amount, step)
|
fun.(start, amount, step)
|
||||||
|
|
||||||
{:error, module} ->
|
{:error, module} ->
|
||||||
|
|||||||
@@ -3555,10 +3555,12 @@ defmodule Kernel do
|
|||||||
not bootstrapped?(Macro) ->
|
not bootstrapped?(Macro) ->
|
||||||
nil
|
nil
|
||||||
|
|
||||||
not function? and __CALLER__.context == :match ->
|
not function? and (__CALLER__.context == :match or __CALLER__.context == :guard) ->
|
||||||
raise ArgumentError,
|
raise ArgumentError,
|
||||||
"""
|
"""
|
||||||
invalid write attribute syntax. If you want to define an attribute, don't do this:
|
invalid usage of module attributes. Module attributes cannot be used inside \
|
||||||
|
pattern matching (and guards) outside of a function. If you are trying to \
|
||||||
|
define an attribute, do not do this:
|
||||||
|
|
||||||
@foo = :value
|
@foo = :value
|
||||||
|
|
||||||
|
|||||||
@@ -8,12 +8,11 @@ Elixir applies bug fixes only to the latest minor branch. Security patches are a
|
|||||||
|
|
||||||
Elixir version | Support
|
Elixir version | Support
|
||||||
:------------- | :-----------------------------
|
:------------- | :-----------------------------
|
||||||
1.15 | Development
|
1.15 | Bug fixes and security patches
|
||||||
1.14 | Bug fixes and security patches
|
1.14 | Security patches only
|
||||||
1.13 | Security patches only
|
1.13 | Security patches only
|
||||||
1.12 | Security patches only
|
1.12 | Security patches only
|
||||||
1.11 | Security patches only
|
1.11 | Security patches only
|
||||||
1.10 | Security patches only
|
|
||||||
|
|
||||||
New releases are announced in the read-only [announcements mailing list](https://groups.google.com/group/elixir-lang-ann). All security releases [will be tagged with `[security]`](https://groups.google.com/forum/#!searchin/elixir-lang-ann/%5Bsecurity%5D%7Csort:date).
|
New releases are announced in the read-only [announcements mailing list](https://groups.google.com/group/elixir-lang-ann). All security releases [will be tagged with `[security]`](https://groups.google.com/forum/#!searchin/elixir-lang-ann/%5Bsecurity%5D%7Csort:date).
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
tmp/
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
+46
@@ -0,0 +1,46 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Usage:
|
||||||
|
#
|
||||||
|
# With Elixir archive:
|
||||||
|
#
|
||||||
|
# ELIXIR_ZIP=Precompiled.zip OTP_VERSION=25.3.2.2 ./build.sh
|
||||||
|
#
|
||||||
|
# With Elixir version:
|
||||||
|
#
|
||||||
|
# ELIXIR_VERSION=1.14.5 OTP_VERSION=25.3.2.2 ./build.sh
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
OTP_VERSION="${OTP_VERSION:-26.0}"
|
||||||
|
otp_release=`echo "${OTP_VERSION}" | cut -d. -f1`
|
||||||
|
|
||||||
|
mkdir -p tmp
|
||||||
|
|
||||||
|
ELIXIR_VERSION="${ELIXIR_VERSION:-}"
|
||||||
|
if [ -n "${ELIXIR_VERSION}" ]; then
|
||||||
|
ELIXIR_ZIP="tmp/elixir-${ELIXIR_VERSION}-otp-${otp_release}.zip"
|
||||||
|
if [ ! -f "${ELIXIR_ZIP}" ]; then
|
||||||
|
url="https://github.com/elixir-lang/elixir/releases/download/v${ELIXIR_VERSION}/elixir-otp-${otp_release}.zip"
|
||||||
|
echo "downloading ${url}"
|
||||||
|
curl --fail -L -o "${ELIXIR_ZIP}" "${url}"
|
||||||
|
fi
|
||||||
|
basename=elixir-${ELIXIR_VERSION}-otp-${otp_release}
|
||||||
|
else
|
||||||
|
basename=elixir-otp-${otp_release}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "tmp/${basename}" ]; then
|
||||||
|
unzip -d "tmp/${basename}" "${ELIXIR_ZIP}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# brew install makensis
|
||||||
|
# apt install -y nsis
|
||||||
|
# choco install -y nsis
|
||||||
|
export PATH="/c/Program Files (x86)/NSIS:${PATH}"
|
||||||
|
makensis \
|
||||||
|
-X"OutFile tmp\\${basename}.exe" \
|
||||||
|
-DOTP_VERSION=${OTP_VERSION} \
|
||||||
|
-DOTP_RELEASE="${otp_release}" \
|
||||||
|
-DELIXIR_DIR=tmp\\${basename} \
|
||||||
|
installer.nsi
|
||||||
|
|
||||||
|
echo "Installer path: tmp/${basename}.exe"
|
||||||
@@ -0,0 +1,209 @@
|
|||||||
|
!include "MUI2.nsh"
|
||||||
|
!include "StrFunc.nsh"
|
||||||
|
${Using:StrFunc} StrStr
|
||||||
|
${Using:StrFunc} UnStrStr
|
||||||
|
${Using:StrFunc} UnStrRep
|
||||||
|
|
||||||
|
Name "Elixir"
|
||||||
|
ManifestDPIAware true
|
||||||
|
Unicode True
|
||||||
|
InstallDir "$PROGRAMFILES64\Elixir"
|
||||||
|
!define MUI_ICON "assets\drop.ico"
|
||||||
|
|
||||||
|
; Install Page: Install Erlang/OTP
|
||||||
|
|
||||||
|
Page custom CheckOTPPageShow CheckOTPPageLeave
|
||||||
|
|
||||||
|
var Dialog
|
||||||
|
var DownloadOTPLink
|
||||||
|
var InstalledERTSVersion
|
||||||
|
var InstalledOTPRelease
|
||||||
|
var OTPPath
|
||||||
|
Function CheckOTPPageShow
|
||||||
|
!insertmacro MUI_HEADER_TEXT "Checking Erlang/OTP" ""
|
||||||
|
|
||||||
|
nsDialogs::Create 1018
|
||||||
|
Pop $Dialog
|
||||||
|
|
||||||
|
${If} $Dialog == error
|
||||||
|
Abort
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
EnumRegKey $0 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang" 0
|
||||||
|
ReadRegStr $1 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang\$0" ""
|
||||||
|
StrCpy $InstalledERTSVersion $0
|
||||||
|
StrCpy $OTPPath $1
|
||||||
|
|
||||||
|
${If} $1 == ""
|
||||||
|
${NSD_CreateLabel} 0 0 100% 20u "Couldn't find existing Erlang/OTP installation. Click the link below to download and install it before proceeding."
|
||||||
|
${NSD_CreateLink} 0 25u 100% 20u "Download Erlang/OTP ${OTP_RELEASE}"
|
||||||
|
Pop $DownloadOTPLink
|
||||||
|
${NSD_OnClick} $DownloadOTPLink OpenOTPDownloads
|
||||||
|
${Else}
|
||||||
|
nsExec::ExecToStack `$OTPPath\bin\erl.exe -noinput -eval "\
|
||||||
|
io:put_chars(erlang:system_info(otp_release)),\
|
||||||
|
halt()."`
|
||||||
|
Pop $0
|
||||||
|
Pop $1
|
||||||
|
|
||||||
|
${If} $0 == 0
|
||||||
|
StrCpy $InstalledOTPRelease $1
|
||||||
|
${If} $InstalledOTPRelease == ${OTP_RELEASE}
|
||||||
|
${NSD_CreateLabel} 0 0 100% 20u "Found existing Erlang/OTP $InstalledOTPRelease installation at $OTPPath. Please proceed."
|
||||||
|
${ElseIf} $2 < ${OTP_RELEASE}
|
||||||
|
${NSD_CreateLabel} 0 0 100% 30u "Found existing Erlang/OTP $InstalledOTPRelease installation at $OTPPath but this Elixir installer was precompiled for Erlang/OTP ${OTP_RELEASE}. \
|
||||||
|
We recommend checking if there is an Elixir version precompiled for Erlang/OTP $InstalledOTPRelease. Otherwise, proceed."
|
||||||
|
${Else}
|
||||||
|
SetErrorlevel 5
|
||||||
|
MessageBox MB_ICONSTOP "Found existing Erlang/OTP $InstalledOTPRelease installation at $OTPPath but this Elixir version was precompiled for Erlang/OTP ${OTP_RELEASE}. \
|
||||||
|
Please upgrade your Erlang/OTP version or choose an Elixir installer matching your Erlang/OTP version"
|
||||||
|
Quit
|
||||||
|
${EndIf}
|
||||||
|
${Else}
|
||||||
|
SetErrorlevel 5
|
||||||
|
MessageBox MB_ICONSTOP "Found existing Erlang/OTP installation at $OTPPath but checking it exited with $0: $1"
|
||||||
|
Quit
|
||||||
|
${EndIf}
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
nsDialogs::Show
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function OpenOTPDownloads
|
||||||
|
ExecShell "open" "https://www.erlang.org/downloads/${OTP_RELEASE}"
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function CheckOTPPageLeave
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
; Install Page: Files
|
||||||
|
|
||||||
|
!insertmacro MUI_PAGE_DIRECTORY
|
||||||
|
!insertmacro MUI_PAGE_INSTFILES
|
||||||
|
|
||||||
|
; Install Page: Finish
|
||||||
|
|
||||||
|
Page custom FinishPageShow FinishPageLeave
|
||||||
|
|
||||||
|
var AddOTPToPathCheckbox
|
||||||
|
var AddElixirToPathCheckbox
|
||||||
|
Function FinishPageShow
|
||||||
|
!insertmacro MUI_HEADER_TEXT "Finish Setup" ""
|
||||||
|
|
||||||
|
nsDialogs::Create 1018
|
||||||
|
Pop $Dialog
|
||||||
|
|
||||||
|
${If} $Dialog == error
|
||||||
|
Abort
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
${NSD_CreateCheckbox} 0 0 195u 10u "&Add $INSTDIR\bin to %PATH%"
|
||||||
|
Pop $AddElixirToPathCheckbox
|
||||||
|
SendMessage $AddElixirToPathCheckbox ${BM_SETCHECK} ${BST_CHECKED} 0
|
||||||
|
|
||||||
|
EnumRegKey $0 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang" 0
|
||||||
|
ReadRegStr $0 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang\$0" ""
|
||||||
|
StrCpy $OTPPath $0
|
||||||
|
${If} $0 != ""
|
||||||
|
${NSD_CreateCheckbox} 0 20u 195u 10u "&Add $0\bin to %PATH%"
|
||||||
|
Pop $AddOTPToPathCheckbox
|
||||||
|
SendMessage $AddOTPToPathCheckbox ${BM_SETCHECK} ${BST_CHECKED} 0
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
nsDialogs::Show
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function FinishPageLeave
|
||||||
|
${NSD_GetState} $AddOTPToPathCheckbox $0
|
||||||
|
${If} $0 <> ${BST_UNCHECKED}
|
||||||
|
ReadRegStr $0 HKCU "Environment" "Path"
|
||||||
|
${StrStr} $1 "$0" "$OTPPath\bin"
|
||||||
|
${If} $1 == ""
|
||||||
|
WriteRegExpandStr HKCU "Environment" "Path" "$OTPPath\bin;$0"
|
||||||
|
${Else}
|
||||||
|
MessageBox MB_OK "$OTPPath\bin already in %PATH%"
|
||||||
|
${EndIf}
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
${NSD_GetState} $AddElixirToPathCheckbox $0
|
||||||
|
${If} $0 <> ${BST_UNCHECKED}
|
||||||
|
ReadRegStr $0 HKCU "Environment" "Path"
|
||||||
|
${StrStr} $1 "$0" "$INSTDIR\bin"
|
||||||
|
${If} $1 == ""
|
||||||
|
WriteRegExpandStr HKCU "Environment" "Path" "$INSTDIR\bin;$0"
|
||||||
|
${Else}
|
||||||
|
MessageBox MB_OK "$INSTDIR\bin already in %PATH%"
|
||||||
|
${EndIf}
|
||||||
|
${EndIf}
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Section "Install Elixir" SectionElixir
|
||||||
|
SetOutPath "$INSTDIR"
|
||||||
|
File /r "${ELIXIR_DIR}\"
|
||||||
|
|
||||||
|
WriteUninstaller "Uninstall.exe"
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
; Uninstall Page: Files
|
||||||
|
|
||||||
|
!insertmacro MUI_UNPAGE_DIRECTORY
|
||||||
|
!insertmacro MUI_UNPAGE_INSTFILES
|
||||||
|
|
||||||
|
Section "Uninstall"
|
||||||
|
RMDir /r "$INSTDIR"
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
; Uninstall Page: Finish
|
||||||
|
|
||||||
|
var RemoveOTPFromPathCheckbox
|
||||||
|
var RemoveElixirFromPathCheckbox
|
||||||
|
Function un.FinishPageShow
|
||||||
|
!insertmacro MUI_HEADER_TEXT "Finish Setup" ""
|
||||||
|
|
||||||
|
nsDialogs::Create 1018
|
||||||
|
Pop $Dialog
|
||||||
|
|
||||||
|
${If} $Dialog == error
|
||||||
|
Abort
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
ReadRegStr $0 HKCU "Environment" "Path"
|
||||||
|
${UnStrStr} $1 "$0" "$INSTDIR\bin"
|
||||||
|
${If} $1 != ""
|
||||||
|
${NSD_CreateCheckbox} 0 0 195u 10u "&Remove $INSTDIR\bin from %PATH%"
|
||||||
|
Pop $RemoveElixirFromPathCheckbox
|
||||||
|
SendMessage $RemoveElixirFromPathCheckbox ${BM_SETCHECK} ${BST_CHECKED} 0
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
EnumRegKey $1 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang" 0
|
||||||
|
ReadRegStr $1 HKLM "SOFTWARE\WOW6432NODE\Ericsson\Erlang\$1" ""
|
||||||
|
StrCpy $OTPPath $1
|
||||||
|
${UnStrStr} $1 "$0" "$OTPPath\bin"
|
||||||
|
${If} $1 != ""
|
||||||
|
${NSD_CreateCheckbox} 0 20u 195u 10u "&Remove $OTPPath\bin from %PATH%"
|
||||||
|
Pop $RemoveOTPFromPathCheckbox
|
||||||
|
SendMessage $RemoveOTPFromPathCheckbox ${BM_SETCHECK} ${BST_CHECKED} 0
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
nsDialogs::Show
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function un.FinishPageLeave
|
||||||
|
ReadRegStr $0 HKCU "Environment" "Path"
|
||||||
|
|
||||||
|
${NSD_GetState} $RemoveOTPFromPathCheckbox $1
|
||||||
|
${If} $1 <> ${BST_UNCHECKED}
|
||||||
|
${UnStrRep} $0 "$0" "$OTPPath\bin;" ""
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
${NSD_GetState} $RemoveElixirFromPathCheckbox $1
|
||||||
|
${If} $1 <> ${BST_UNCHECKED}
|
||||||
|
${UnStrRep} $0 "$0" "$INSTDIR\bin;" ""
|
||||||
|
${EndIf}
|
||||||
|
|
||||||
|
WriteRegExpandStr HKCU "Environment" "Path" "$0"
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
UninstPage custom un.FinishPageShow un.FinishPageLeave
|
||||||
|
|
||||||
|
!insertmacro MUI_LANGUAGE "English"
|
||||||
@@ -510,12 +510,15 @@ get_moduledoc_meta(Set) ->
|
|||||||
|
|
||||||
get_docs(Set, Module, Definitions, Kind) ->
|
get_docs(Set, Module, Definitions, Kind) ->
|
||||||
[{Key,
|
[{Key,
|
||||||
erl_anno:new(Line),
|
maybe_generated(erl_anno:new(Line), Ctx),
|
||||||
[signature_to_binary(Module, Name, Signature)],
|
[signature_to_binary(Module, Name, Signature)],
|
||||||
doc_value(Doc, Name),
|
doc_value(Doc, Name),
|
||||||
Meta
|
Meta
|
||||||
} || {Name, Arity} <- Definitions,
|
} || {Name, Arity} <- Definitions,
|
||||||
{Key, _Ctx, Line, Signature, Doc, Meta} <- ets:lookup(Set, {Kind, Name, Arity})].
|
{Key, Ctx, Line, Signature, Doc, Meta} <- ets:lookup(Set, {Kind, Name, Arity})].
|
||||||
|
|
||||||
|
maybe_generated(Ann, nil) -> Ann;
|
||||||
|
maybe_generated(Ann, _Ctx) -> erl_anno:set_generated(true, Ann).
|
||||||
|
|
||||||
get_callback_docs(Set, Callbacks) ->
|
get_callback_docs(Set, Callbacks) ->
|
||||||
[{Key,
|
[{Key,
|
||||||
|
|||||||
@@ -1030,8 +1030,8 @@ extract_heredoc_with_interpolation(Line, Column, Scope, Interpol, T, H) ->
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
error ->
|
error ->
|
||||||
Message = "heredoc allows only zero or more whitespace characters followed by a new line after ",
|
Message = "heredoc allows only whitespace characters followed by a new line after opening ",
|
||||||
{error, {Line, Column, io_lib:format(Message, []), [H, H, H]}}
|
{error, {Line, Column + 3, io_lib:format(Message, []), [H, H, H]}}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
extract_heredoc_header("\r\n" ++ Rest) ->
|
extract_heredoc_header("\r\n" ++ Rest) ->
|
||||||
@@ -1796,7 +1796,7 @@ prune_tokens([{OpType, _, _} | _] = Tokens, [], Terminators)
|
|||||||
OpType =:= in_match_op; OpType =:= type_op; OpType =:= dual_op; OpType =:= mult_op;
|
OpType =:= in_match_op; OpType =:= type_op; OpType =:= dual_op; OpType =:= mult_op;
|
||||||
OpType =:= power_op; OpType =:= concat_op; OpType =:= range_op; OpType =:= xor_op;
|
OpType =:= power_op; OpType =:= concat_op; OpType =:= range_op; OpType =:= xor_op;
|
||||||
OpType =:= pipe_op; OpType =:= stab_op; OpType =:= when_op; OpType =:= assoc_op;
|
OpType =:= pipe_op; OpType =:= stab_op; OpType =:= when_op; OpType =:= assoc_op;
|
||||||
OpType =:= rel_op; OpType =:= ternary_op ->
|
OpType =:= rel_op; OpType =:= ternary_op; OpType =:= capture_op ->
|
||||||
{Tokens, Terminators};
|
{Tokens, Terminators};
|
||||||
%%% or we traverse until the end.
|
%%% or we traverse until the end.
|
||||||
prune_tokens([_ | Tokens], Opener, Terminators) ->
|
prune_tokens([_ | Tokens], Opener, Terminators) ->
|
||||||
|
|||||||
@@ -1098,6 +1098,8 @@ defmodule CodeFragmentTest do
|
|||||||
|
|
||||||
test "keeps operators" do
|
test "keeps operators" do
|
||||||
assert cc2q("1 + 2") == s2q("1 + __cursor__()")
|
assert cc2q("1 + 2") == s2q("1 + __cursor__()")
|
||||||
|
assert cc2q("&foo") == s2q("&__cursor__()")
|
||||||
|
assert cc2q("&foo/") == s2q("&foo/__cursor__()")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "keeps function calls without parens" do
|
test "keeps function calls without parens" do
|
||||||
@@ -1200,11 +1202,6 @@ defmodule CodeFragmentTest do
|
|||||||
assert cc2q("(fn x, y -> x + y end") == s2q("(__cursor__())")
|
assert cc2q("(fn x, y -> x + y end") == s2q("(__cursor__())")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "removes captures" do
|
|
||||||
assert cc2q("[& &1") == s2q("[__cursor__()]")
|
|
||||||
assert cc2q("[&(&1") == s2q("[__cursor__()]")
|
|
||||||
end
|
|
||||||
|
|
||||||
test "removes closed terminators" do
|
test "removes closed terminators" do
|
||||||
assert cc2q("foo([1, 2, 3]") == s2q("foo(__cursor__())")
|
assert cc2q("foo([1, 2, 3]") == s2q("foo(__cursor__())")
|
||||||
assert cc2q("foo({1, 2, 3}") == s2q("foo(__cursor__())")
|
assert cc2q("foo({1, 2, 3}") == s2q("foo(__cursor__())")
|
||||||
|
|||||||
@@ -1102,6 +1102,16 @@ defmodule EnumTest do
|
|||||||
[2, 1, 3]
|
[2, 1, 3]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "slice on MapSets" do
|
||||||
|
assert MapSet.new(1..10) |> Enum.slice(0, 2) |> Enum.count() == 2
|
||||||
|
assert MapSet.new(1..3) |> Enum.slice(0, 10) |> Enum.count() == 3
|
||||||
|
assert MapSet.new(1..10) |> Enum.slice(0..1) |> Enum.count() == 2
|
||||||
|
assert MapSet.new(1..3) |> Enum.slice(0..10) |> Enum.count() == 3
|
||||||
|
|
||||||
|
assert MapSet.new(1..10) |> Enum.slice(0..4//2) |> Enum.count() == 3
|
||||||
|
assert MapSet.new(1..10) |> Enum.slice(0..5//2) |> Enum.count() == 3
|
||||||
|
end
|
||||||
|
|
||||||
test "sort/1" do
|
test "sort/1" do
|
||||||
assert Enum.sort([5, 3, 2, 4, 1]) == [1, 2, 3, 4, 5]
|
assert Enum.sort([5, 3, 2, 4, 1]) == [1, 2, 3, 4, 5]
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -381,4 +381,30 @@ defmodule Kernel.DocsTest do
|
|||||||
{{:fuz, 0}, :none}
|
{{:fuz, 0}, :none}
|
||||||
] = Enum.sort(function_docs)
|
] = Enum.sort(function_docs)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "generated functions are annotated as such" do
|
||||||
|
write_beam(
|
||||||
|
defmodule ToBeUsed do
|
||||||
|
defmacro __using__(_) do
|
||||||
|
quote do
|
||||||
|
@doc "Hello"
|
||||||
|
def foo, do: :bar
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
|
write_beam(
|
||||||
|
defmodule WillBeUsing do
|
||||||
|
use ToBeUsed
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
|
{:docs_v1, _, _, _, _, _, docs} = Code.fetch_docs(WillBeUsing)
|
||||||
|
|
||||||
|
assert [
|
||||||
|
{{:function, :foo, 0}, [generated: true, location: 399], ["foo()"],
|
||||||
|
%{"en" => "Hello"}, %{}}
|
||||||
|
] = docs
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -538,7 +538,7 @@ defmodule Kernel.ParserTest do
|
|||||||
describe "syntax errors" do
|
describe "syntax errors" do
|
||||||
test "invalid heredoc start" do
|
test "invalid heredoc start" do
|
||||||
assert_syntax_error(
|
assert_syntax_error(
|
||||||
~r/nofile:1:1: heredoc allows only zero or more whitespace characters followed by a new line after \"\"\"/,
|
~r/nofile:1:4: heredoc allows only whitespace characters followed by a new line after opening \"\"\"/,
|
||||||
~c"\"\"\"bar\n\"\"\""
|
~c"\"\"\"bar\n\"\"\""
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -831,11 +831,25 @@ defmodule KernelTest do
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "matching attribute" do
|
test "matching attribute" do
|
||||||
assert_raise ArgumentError, ~r"invalid write attribute syntax", fn ->
|
assert_raise ArgumentError, ~r"invalid usage of module attributes", fn ->
|
||||||
defmodule MatchAttributeInModule do
|
defmodule MatchAttributeInModule do
|
||||||
@foo = 42
|
@foo = 42
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assert_raise ArgumentError, ~r"invalid usage of module attributes", fn ->
|
||||||
|
defmodule MatchAttributeInModule do
|
||||||
|
@foo 16
|
||||||
|
<<_::@foo>> = "ab"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_raise ArgumentError, ~r"invalid usage of module attributes", fn ->
|
||||||
|
defmodule MatchAttributeInModule do
|
||||||
|
@foo 16
|
||||||
|
<<_::size(@foo)>> = "ab"
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -293,8 +293,9 @@ defmodule ExUnit.Runner do
|
|||||||
{test_module, invalid_tests, []}
|
{test_module, invalid_tests, []}
|
||||||
|
|
||||||
{:DOWN, ^module_ref, :process, ^module_pid, error} ->
|
{:DOWN, ^module_ref, :process, ^module_pid, error} ->
|
||||||
|
invalid_tests = Enum.map(tests, &%{&1 | state: {:invalid, test_module}})
|
||||||
test_module = %{test_module | state: failed({:EXIT, module_pid}, error, [])}
|
test_module = %{test_module | state: failed({:EXIT, module_pid}, error, [])}
|
||||||
{test_module, [], []}
|
{test_module, invalid_tests, []}
|
||||||
end
|
end
|
||||||
|
|
||||||
timeout = get_timeout(config, %{})
|
timeout = get_timeout(config, %{})
|
||||||
|
|||||||
@@ -124,6 +124,22 @@ defmodule ExUnit.CallbacksTest do
|
|||||||
"** (MatchError) no match of right hand side value: :error"
|
"** (MatchError) no match of right hand side value: :error"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "doesn't choke on setup_all exits" do
|
||||||
|
defmodule SetupAllExitTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
setup_all _ do
|
||||||
|
Process.exit(self(), :error)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "ok" do
|
||||||
|
assert true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert capture_io(fn -> ExUnit.run() end) =~ "1 test, 0 failures, 1 invalid"
|
||||||
|
end
|
||||||
|
|
||||||
test "doesn't choke on dead supervisor" do
|
test "doesn't choke on dead supervisor" do
|
||||||
defmodule StartSupervisedErrorTest do
|
defmodule StartSupervisedErrorTest do
|
||||||
use ExUnit.Case
|
use ExUnit.Case
|
||||||
|
|||||||
@@ -689,6 +689,8 @@ defmodule IEx.Pry do
|
|||||||
[asts_string, :faint, " #=> ", :reset, inspect(value, options), "\n\n"]
|
[asts_string, :faint, " #=> ", :reset, inspect(value, options), "\n\n"]
|
||||||
|> IO.ANSI.format()
|
|> IO.ANSI.format()
|
||||||
|> IO.write()
|
|> IO.write()
|
||||||
|
|
||||||
|
value
|
||||||
end
|
end
|
||||||
|
|
||||||
defp chunk_pipeline_asts_by_line(asts, %Macro.Env{line: env_line}) do
|
defp chunk_pipeline_asts_by_line(asts, %Macro.Env{line: env_line}) do
|
||||||
|
|||||||
+25
-18
@@ -210,7 +210,7 @@ defmodule Logger do
|
|||||||
metadata: [:error_code, :file]
|
metadata: [:error_code, :file]
|
||||||
|
|
||||||
Or to configure default handler, for instance, to log into a file with
|
Or to configure default handler, for instance, to log into a file with
|
||||||
built-in support for log rotation:
|
built-in support for log rotation and compression:
|
||||||
|
|
||||||
config :logger, :default_handler,
|
config :logger, :default_handler,
|
||||||
config: [
|
config: [
|
||||||
@@ -218,9 +218,18 @@ defmodule Logger do
|
|||||||
filesync_repeat_interval: 5000,
|
filesync_repeat_interval: 5000,
|
||||||
file_check: 5000,
|
file_check: 5000,
|
||||||
max_no_bytes: 10_000_000,
|
max_no_bytes: 10_000_000,
|
||||||
max_no_files: 5
|
max_no_files: 5,
|
||||||
|
compress_on_rotate: true
|
||||||
]
|
]
|
||||||
|
|
||||||
|
See [`:logger_std_h`](`:logger_std_h`) for all relevant configuration,
|
||||||
|
including overload protection. Or set `:default_handler` to false to
|
||||||
|
disable the default logging altogether:
|
||||||
|
|
||||||
|
config :logger, :default_handler, false
|
||||||
|
|
||||||
|
How to add new handlers is covered in later sections.
|
||||||
|
|
||||||
> #### Keywords or maps {: .tip}
|
> #### Keywords or maps {: .tip}
|
||||||
>
|
>
|
||||||
> While Erlang's logger expects `:config` to be a map, Elixir's Logger
|
> While Erlang's logger expects `:config` to be a map, Elixir's Logger
|
||||||
@@ -231,14 +240,6 @@ defmodule Logger do
|
|||||||
> When reading the handler configuration using Erlang's APIs,
|
> When reading the handler configuration using Erlang's APIs,
|
||||||
> the configuration will always be read (and written) as a map.
|
> the configuration will always be read (and written) as a map.
|
||||||
|
|
||||||
See [`:logger_std_h`](`:logger_std_h`) for all relevant configuration,
|
|
||||||
including overload protection. Or set `:default_handler` to false to
|
|
||||||
disable the default logging altogether:
|
|
||||||
|
|
||||||
config :logger, :default_handler, false
|
|
||||||
|
|
||||||
How to add new handlers is covered in later sections.
|
|
||||||
|
|
||||||
### Compile configuration
|
### Compile configuration
|
||||||
|
|
||||||
The following configuration must be set via config files (such as
|
The following configuration must be set via config files (such as
|
||||||
@@ -329,16 +330,19 @@ defmodule Logger do
|
|||||||
default handler, but you can use Erlang's [`:logger`](`:logger`) module
|
default handler, but you can use Erlang's [`:logger`](`:logger`) module
|
||||||
to add other handlers too.
|
to add other handlers too.
|
||||||
|
|
||||||
Erlang/OTP handlers must be listed under your own application. For example,
|
Erlang/OTP handlers must be listed under your own application.
|
||||||
to setup an additional handler that writes to disk:
|
For example, to setup an additional handler, so you write to
|
||||||
|
console and file:
|
||||||
|
|
||||||
config :my_app, :logger, [
|
config :my_app, :logger, [
|
||||||
{:handler, :disk_log, :logger_disk_log_h, %{
|
{:handler, :file_log, :logger_std_h, %{
|
||||||
config: %{
|
config: %{
|
||||||
file: 'system.log',
|
file: ~c"system.log",
|
||||||
filesync_repeat_interval: 5000,
|
filesync_repeat_interval: 5000,
|
||||||
|
file_check: 5000,
|
||||||
max_no_bytes: 10_000_000,
|
max_no_bytes: 10_000_000,
|
||||||
max_no_files: 5
|
max_no_files: 5,
|
||||||
|
compress_on_rotate: true
|
||||||
},
|
},
|
||||||
formatter: Logger.Formatter.new()
|
formatter: Logger.Formatter.new()
|
||||||
}}
|
}}
|
||||||
@@ -355,9 +359,12 @@ defmodule Logger do
|
|||||||
flexibility but they should avoid performing any long running action in
|
flexibility but they should avoid performing any long running action in
|
||||||
such handlers, as it may slow down the action being executed considerably.
|
such handlers, as it may slow down the action being executed considerably.
|
||||||
At the moment, there is no built-in overload protection for Erlang handlers,
|
At the moment, there is no built-in overload protection for Erlang handlers,
|
||||||
so it is your responsibility to implement it. Alternatively, you can use the
|
so it is your responsibility to implement it.
|
||||||
[`:logger_backends`](https://github.com/elixir-lang/logger_backends)
|
|
||||||
project.
|
Alternatively, you can use the
|
||||||
|
[`:logger_backends`](https://github.com/elixir-lang/logger_backends) project.
|
||||||
|
It sets up a log handler with overload protection and allows incoming events
|
||||||
|
to be dispatched to multiple backends.
|
||||||
|
|
||||||
## Backends and backwards compatibility
|
## Backends and backwards compatibility
|
||||||
|
|
||||||
|
|||||||
@@ -136,8 +136,12 @@ defmodule Mix.AppLoader do
|
|||||||
end
|
end
|
||||||
|
|
||||||
# We have processed all apps.
|
# We have processed all apps.
|
||||||
defp traverse_apps([], _seen, _deps_children, _builtin_paths, _lib_path) do
|
defp traverse_apps([], seen, _deps_children, builtin_paths, _lib_path) do
|
||||||
[]
|
# We want to keep erts in the load path but it doesn't require to be loaded.
|
||||||
|
case builtin_paths do
|
||||||
|
%{erts: path} when not is_map_key(seen, :erts) -> [{:erts, path}]
|
||||||
|
%{} -> []
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp app_children(app) do
|
defp app_children(app) do
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ defmodule Mix.Tasks.Compile.All do
|
|||||||
{loaded_paths, loaded_modules} =
|
{loaded_paths, loaded_modules} =
|
||||||
Mix.AppLoader.load_apps(apps, deps, config, {[], []}, fn {app, path}, {paths, mods} ->
|
Mix.AppLoader.load_apps(apps, deps, config, {[], []}, fn {app, path}, {paths, mods} ->
|
||||||
paths = if path, do: [path | paths], else: paths
|
paths = if path, do: [path | paths], else: paths
|
||||||
mods = if app_cache, do: [{app, Application.spec(app, :modules)} | mods], else: mods
|
mods = if app_cache, do: [{app, Application.spec(app, :modules) || []} | mods], else: mods
|
||||||
{paths, mods}
|
{paths, mods}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|||||||
@@ -38,8 +38,9 @@ defmodule Mix.Tasks.Xref do
|
|||||||
$ mix xref trace lib/my_app/router.ex --label compile
|
$ mix xref trace lib/my_app/router.ex --label compile
|
||||||
|
|
||||||
If you have an umbrella application, we also recommend using the
|
If you have an umbrella application, we also recommend using the
|
||||||
`--include-siblings` flag to see the dependencies on other
|
`--include-siblings` flag to see the dependencies from sibling
|
||||||
umbrella applications.
|
applications. The `trace` command is not currently supported at the
|
||||||
|
umbrella root.
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
@@ -222,6 +223,12 @@ defmodule Mix.Tasks.Xref do
|
|||||||
lib/a.ex
|
lib/a.ex
|
||||||
└── lib/b.ex (compile)
|
└── lib/b.ex (compile)
|
||||||
|
|
||||||
|
If you have an umbrella application, we also recommend using the
|
||||||
|
`--include-siblings` flag to see the dependencies from sibling
|
||||||
|
applications. When invoked at the umbrella root, the `graph`
|
||||||
|
command will list all files from all umbrella children, without
|
||||||
|
any namespacing.
|
||||||
|
|
||||||
### Dependency types
|
### Dependency types
|
||||||
|
|
||||||
Elixir tracks three types of dependencies between modules: compile,
|
Elixir tracks three types of dependencies between modules: compile,
|
||||||
@@ -289,12 +296,6 @@ defmodule Mix.Tasks.Xref do
|
|||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def run(args) do
|
def run(args) do
|
||||||
if Mix.Project.umbrella?() do
|
|
||||||
Mix.raise(
|
|
||||||
"mix xref is not supported in the umbrella root. Please run it inside the umbrella applications instead"
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
Mix.Task.run("compile", args)
|
Mix.Task.run("compile", args)
|
||||||
Mix.Task.reenable("xref")
|
Mix.Task.reenable("xref")
|
||||||
|
|
||||||
@@ -302,9 +303,11 @@ defmodule Mix.Tasks.Xref do
|
|||||||
|
|
||||||
case args do
|
case args do
|
||||||
["callers", module] ->
|
["callers", module] ->
|
||||||
|
no_umbrella!("callers")
|
||||||
handle_callers(module, opts)
|
handle_callers(module, opts)
|
||||||
|
|
||||||
["trace", file] ->
|
["trace", file] ->
|
||||||
|
no_umbrella!("trace")
|
||||||
handle_trace(file, opts)
|
handle_trace(file, opts)
|
||||||
|
|
||||||
["graph"] ->
|
["graph"] ->
|
||||||
@@ -327,6 +330,14 @@ defmodule Mix.Tasks.Xref do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp no_umbrella!(task) do
|
||||||
|
if Mix.Project.umbrella?() do
|
||||||
|
Mix.raise(
|
||||||
|
"mix xref #{task} is not supported in the umbrella root. Please run it inside the umbrella applications instead"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Returns a list of information of all the runtime function calls in the project.
|
Returns a list of information of all the runtime function calls in the project.
|
||||||
|
|
||||||
@@ -1058,12 +1069,18 @@ defmodule Mix.Tasks.Xref do
|
|||||||
|
|
||||||
defp manifests(opts) do
|
defp manifests(opts) do
|
||||||
siblings =
|
siblings =
|
||||||
if opts[:include_siblings] do
|
cond do
|
||||||
for %{scm: Mix.SCM.Path, opts: opts} <- Mix.Dep.cached(),
|
Mix.Project.umbrella?() ->
|
||||||
opts[:in_umbrella],
|
for %{opts: opts} <- Mix.Dep.Umbrella.cached(),
|
||||||
do: Path.join([opts[:build], ".mix", @manifest])
|
do: Path.join([opts[:build], ".mix", @manifest])
|
||||||
else
|
|
||||||
[]
|
opts[:include_siblings] ->
|
||||||
|
for %{scm: Mix.SCM.Path, opts: opts} <- Mix.Dep.cached(),
|
||||||
|
opts[:in_umbrella],
|
||||||
|
do: Path.join([opts[:build], ".mix", @manifest])
|
||||||
|
|
||||||
|
true ->
|
||||||
|
[]
|
||||||
end
|
end
|
||||||
|
|
||||||
[Path.join(Mix.Project.manifest_path(), @manifest) | siblings]
|
[Path.join(Mix.Project.manifest_path(), @manifest) | siblings]
|
||||||
|
|||||||
@@ -335,6 +335,10 @@ defmodule Mix.Tasks.CompileTest do
|
|||||||
in_fixture("no_mixfile", fn ->
|
in_fixture("no_mixfile", fn ->
|
||||||
assert Mix.Task.run("compile", []) == {:ok, []}
|
assert Mix.Task.run("compile", []) == {:ok, []}
|
||||||
assert :code.where_is_file(~c"parsetools.app") == :non_existing
|
assert :code.where_is_file(~c"parsetools.app") == :non_existing
|
||||||
|
|
||||||
|
# Make sure erts is also kept but not loaded
|
||||||
|
assert {:docs_v1, _, _, _, _, _, _} = Code.fetch_docs(:zlib)
|
||||||
|
assert Application.spec(:erts, :vsn) == nil
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -915,6 +915,43 @@ defmodule Mix.Tasks.XrefTest do
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "generates reports from the umbrella root" do
|
||||||
|
Mix.Project.pop()
|
||||||
|
|
||||||
|
in_fixture("umbrella_dep/deps/umbrella", fn ->
|
||||||
|
Mix.Project.in_project(:umbrella, ".", fn _ ->
|
||||||
|
File.write!("apps/bar/lib/bar.ex", """
|
||||||
|
defmodule Bar do
|
||||||
|
def bar do
|
||||||
|
Foo.foo()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
""")
|
||||||
|
|
||||||
|
Mix.Task.run("compile")
|
||||||
|
Mix.shell().flush()
|
||||||
|
|
||||||
|
Mix.Tasks.Xref.run(["graph", "--format", "stats", "--include-siblings"])
|
||||||
|
|
||||||
|
assert receive_until_no_messages([]) == """
|
||||||
|
Tracked files: 2 (nodes)
|
||||||
|
Compile dependencies: 0 (edges)
|
||||||
|
Exports dependencies: 0 (edges)
|
||||||
|
Runtime dependencies: 1 (edges)
|
||||||
|
Cycles: 0
|
||||||
|
|
||||||
|
Top 2 files with most outgoing dependencies:
|
||||||
|
* lib/bar.ex (1)
|
||||||
|
* lib/foo.ex (0)
|
||||||
|
|
||||||
|
Top 2 files with most incoming dependencies:
|
||||||
|
* lib/foo.ex (1)
|
||||||
|
* lib/bar.ex (0)
|
||||||
|
"""
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
test "generates reports considering siblings inside umbrellas" do
|
test "generates reports considering siblings inside umbrellas" do
|
||||||
Mix.Project.pop()
|
Mix.Project.pop()
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,16 @@
|
|||||||
|
home = Path.expand("../tmp/.home", __DIR__)
|
||||||
|
File.mkdir_p!(home)
|
||||||
|
System.put_env("HOME", home)
|
||||||
|
|
||||||
|
mix = Path.expand("../tmp/.mix", __DIR__)
|
||||||
|
File.mkdir_p!(mix)
|
||||||
|
System.put_env("MIX_HOME", mix)
|
||||||
|
|
||||||
|
System.delete_env("XDG_DATA_HOME")
|
||||||
|
System.delete_env("XDG_CONFIG_HOME")
|
||||||
|
|
||||||
|
## Setup Mix
|
||||||
|
|
||||||
Mix.start()
|
Mix.start()
|
||||||
Mix.shell(Mix.Shell.Process)
|
Mix.shell(Mix.Shell.Process)
|
||||||
Application.put_env(:mix, :colors, enabled: false)
|
Application.put_env(:mix, :colors, enabled: false)
|
||||||
@@ -5,6 +18,8 @@ Application.put_env(:mix, :colors, enabled: false)
|
|||||||
Logger.remove_backend(:console)
|
Logger.remove_backend(:console)
|
||||||
Application.put_env(:logger, :backends, [])
|
Application.put_env(:logger, :backends, [])
|
||||||
|
|
||||||
|
## Setup ExUnit
|
||||||
|
|
||||||
os_exclude = if match?({:win32, _}, :os.type()), do: [unix: true], else: [windows: true]
|
os_exclude = if match?({:win32, _}, :os.type()), do: [unix: true], else: [windows: true]
|
||||||
epmd_exclude = if match?({:win32, _}, :os.type()), do: [epmd: true], else: []
|
epmd_exclude = if match?({:win32, _}, :os.type()), do: [epmd: true], else: []
|
||||||
git_exclude = if Mix.SCM.Git.git_version() <= {1, 7, 4}, do: [git_sparse: true], else: []
|
git_exclude = if Mix.SCM.Git.git_version() <= {1, 7, 4}, do: [git_sparse: true], else: []
|
||||||
@@ -212,18 +227,7 @@ defmodule MixTest.Case do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
## Set up globals
|
## Set up Rebar fixtures
|
||||||
|
|
||||||
home = MixTest.Case.tmp_path(".home")
|
|
||||||
File.mkdir_p!(home)
|
|
||||||
System.put_env("HOME", home)
|
|
||||||
|
|
||||||
mix = MixTest.Case.tmp_path(".mix")
|
|
||||||
File.mkdir_p!(mix)
|
|
||||||
System.put_env("MIX_HOME", mix)
|
|
||||||
|
|
||||||
System.delete_env("XDG_DATA_HOME")
|
|
||||||
System.delete_env("XDG_CONFIG_HOME")
|
|
||||||
|
|
||||||
rebar3_source = System.get_env("REBAR3") || Path.expand("fixtures/rebar3", __DIR__)
|
rebar3_source = System.get_env("REBAR3") || Path.expand("fixtures/rebar3", __DIR__)
|
||||||
[major, minor | _] = String.split(System.version(), ".")
|
[major, minor | _] = String.split(System.version(), ".")
|
||||||
@@ -231,8 +235,6 @@ rebar3_target = Path.join([mix, "elixir", "#{major}-#{minor}", "rebar3"])
|
|||||||
File.mkdir_p!(Path.dirname(rebar3_target))
|
File.mkdir_p!(Path.dirname(rebar3_target))
|
||||||
File.cp!(rebar3_source, rebar3_target)
|
File.cp!(rebar3_source, rebar3_target)
|
||||||
|
|
||||||
## Copy fixtures to tmp
|
|
||||||
|
|
||||||
fixtures = ~w(rebar_dep rebar_override)
|
fixtures = ~w(rebar_dep rebar_override)
|
||||||
|
|
||||||
Enum.each(fixtures, fn fixture ->
|
Enum.each(fixtures, fn fixture ->
|
||||||
@@ -242,12 +244,13 @@ Enum.each(fixtures, fn fixture ->
|
|||||||
File.cp_r!(source, dest)
|
File.cp_r!(source, dest)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
## Generate Git repo fixtures
|
## Set up Git fixtures
|
||||||
|
|
||||||
System.cmd("git", ~w[config --global user.email mix@example.com])
|
System.cmd("git", ~w[config --global user.email mix@example.com])
|
||||||
System.cmd("git", ~w[config --global user.name mix-repo])
|
System.cmd("git", ~w[config --global user.name mix-repo])
|
||||||
System.cmd("git", ~w[config --global init.defaultBranch not-main])
|
System.cmd("git", ~w[config --global init.defaultBranch not-main])
|
||||||
|
|
||||||
# Git repo
|
### Git repo
|
||||||
target = Path.expand("fixtures/git_repo", __DIR__)
|
target = Path.expand("fixtures/git_repo", __DIR__)
|
||||||
|
|
||||||
unless File.dir?(target) do
|
unless File.dir?(target) do
|
||||||
@@ -329,7 +332,7 @@ unless File.dir?(target) do
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Deps on Git repo
|
### Deps on Git repo
|
||||||
target = Path.expand("fixtures/deps_on_git_repo", __DIR__)
|
target = Path.expand("fixtures/deps_on_git_repo", __DIR__)
|
||||||
|
|
||||||
unless File.dir?(target) do
|
unless File.dir?(target) do
|
||||||
@@ -423,7 +426,7 @@ Enum.each([:invalidapp, :invalidvsn, :noappfile, :nosemver, :ok], fn dep ->
|
|||||||
File.mkdir_p!(Path.expand("fixtures/deps_status/deps/#{dep}/.git", __DIR__))
|
File.mkdir_p!(Path.expand("fixtures/deps_status/deps/#{dep}/.git", __DIR__))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
# Archive ebin
|
### Archive ebin
|
||||||
target = Path.expand("fixtures/archive", __DIR__)
|
target = Path.expand("fixtures/archive", __DIR__)
|
||||||
|
|
||||||
unless File.dir?(Path.join(target, "ebin")) do
|
unless File.dir?(Path.join(target, "ebin")) do
|
||||||
|
|||||||
Reference in New Issue
Block a user