Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: elixir-lang/elixir
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.15.3
Choose a base ref
...
head repository: elixir-lang/elixir
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.15.4
Choose a head ref
  • 7 commits
  • 12 files changed
  • 4 contributors

Commits on Jul 16, 2023

  1. Update io.ex (#12800)

    Fix newlines in documentation for IO module
    gmile authored and josevalim committed Jul 16, 2023
    Copy the full SHA
    1dbf121 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    4fbed9f View commit details
  3. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    82c264b View commit details
  4. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    af378de View commit details

Commits on Jul 17, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    7ff97fb View commit details
  2. Copy the full SHA
    bdbdf52 View commit details

Commits on Jul 18, 2023

  1. Release v1.15.4

    josevalim committed Jul 18, 2023
    Copy the full SHA
    c521bdb View commit details
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -117,6 +117,16 @@ in the long term.
See the new `Logger` documentation for more information on the
new features and on compatibility.

## v1.15.4 (2023-07-18)

### 1. Bug fixes

#### Mix

* [mix archive.build] Disable protocol consolidation when building archiveson archive.install
* [mix compile] Track removed files per local dependency (this addresses a bug where files depending on modules from path dependencies always recompiled)
* [mix release] Do not strip relevant chunks from Erlang/OTP 26

## v1.15.3 (2023-07-15)

### 1. Enhancements
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.15.3
1.15.4
2 changes: 1 addition & 1 deletion bin/elixir
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/sh
set -e

ELIXIR_VERSION=1.15.3
ELIXIR_VERSION=1.15.4

if [ $# -eq 0 ] || { [ $# -eq 1 ] && { [ "$1" = "--help" ] || [ "$1" = "-h" ]; }; }; then
cat <<USAGE >&2
2 changes: 1 addition & 1 deletion bin/elixir.bat
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@if defined ELIXIR_CLI_ECHO (@echo on) else (@echo off)

set ELIXIR_VERSION=1.15.3
set ELIXIR_VERSION=1.15.4

setlocal enabledelayedexpansion
if ""%1""=="""" if ""%2""=="""" goto documentation
6 changes: 3 additions & 3 deletions lib/elixir/lib/io.ex
Original file line number Diff line number Diff line change
@@ -593,11 +593,11 @@ defmodule IO do
Another example where you might want to collect a user input
every new line and break on an empty line, followed by removing
redundant new line characters (`"\n"`):
redundant new line characters (`"\\n"`):
IO.stream(:stdio, :line)
|> Enum.take_while(&(&1 != "\n"))
|> Enum.map(&String.replace(&1, "\n", ""))
|> Enum.take_while(&(&1 != "\\n"))
|> Enum.map(&String.replace(&1, "\\n", ""))
"""
@spec stream(device, :line | pos_integer) :: Enumerable.t()
2 changes: 1 addition & 1 deletion lib/ex_unit/lib/ex_unit/case_template.ex
Original file line number Diff line number Diff line change
@@ -130,7 +130,7 @@ defmodule ExUnit.CaseTemplate do
The second argument passed to `use MyCase` gets forwarded to `using/2` too:
defmodule SomeTestCase do
use MyCase, async: true, import_helpers: true, async: true
use MyCase, async: true, import_helpers: true
test "the truth" do
# truth/0 comes from MyApp.TestHelpers:
1 change: 1 addition & 0 deletions lib/iex/lib/iex/introspection.ex
Original file line number Diff line number Diff line change
@@ -293,6 +293,7 @@ defmodule IEx.Introspection do
module.module_info(:exports)
end
|> Enum.sort()
|> Enum.dedup()

result =
for {^function, arity} <- exports,
116 changes: 58 additions & 58 deletions lib/mix/lib/mix/compilers/elixir.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule Mix.Compilers.Elixir do
@moduledoc false

@manifest_vsn 19
@manifest_vsn 20
@checkpoint_vsn 2

import Record
@@ -566,72 +566,72 @@ defmodule Mix.Compilers.Elixir do
Enum.any?(enumerable, &Map.has_key?(map, &1))
end

defp stale_local_deps(local_deps, manifest, stale_modules, modified, old_exports) do
defp stale_local_deps(local_deps, manifest, stale_modules, modified, deps_exports) do
base = Path.basename(manifest)

# The stale modules so far will become both stale_modules and stale_exports,
# as any export from a dependency needs to be recompiled.
stale_modules = Map.from_keys(stale_modules, true)

{stale_modules, stale_exports, new_exports} =
for %{opts: opts} <- local_deps,
manifest = Path.join([opts[:build], ".mix", base]),
Mix.Utils.last_modified(manifest) > modified,
reduce: {stale_modules, stale_modules, []} do
{modules, exports, new_exports} ->
{manifest_modules, manifest_sources} = read_manifest(manifest)

dep_modules =
for module(module: module, timestamp: timestamp) <- manifest_modules,
timestamp > modified,
do: module

# If any module has a compile time dependency on a changed module
# within the dependency, they will be recompiled. However, export
# and runtime dependencies won't have recompiled so we need to
# propagate them to the parent app.
{dep_modules, _, _} =
fixpoint_runtime_modules(manifest_sources, Map.from_keys(dep_modules, true))

# Update exports
{exports, new_exports} =
for {module, _} <- dep_modules, reduce: {exports, new_exports} do
{exports, new_exports} ->
export = exports_md5(module, false)

# If the exports are the same, then the API did not change,
# so we do not mark the export as stale. Note this has to
# be very conservative. If the module is not loaded or if
# the exports were not there, we need to consider it a stale
# export.
exports =
if export && old_exports[module] == export,
do: exports,
else: Map.put(exports, module, true)

# Then we store the new export if any
new_exports =
if export,
do: [{module, export} | new_exports],
else: new_exports

{exports, new_exports}
end

{Map.merge(modules, dep_modules), exports, new_exports}
end
for %{app: app, opts: opts} <- local_deps,
manifest = Path.join([opts[:build], ".mix", base]),
Mix.Utils.last_modified(manifest) > modified,
reduce: {stale_modules, stale_modules, deps_exports} do
{modules, exports, deps_exports} ->
{manifest_modules, manifest_sources} = read_manifest(manifest)

dep_modules =
for module(module: module, timestamp: timestamp) <- manifest_modules,
timestamp > modified,
do: module

# If any module has a compile time dependency on a changed module
# within the dependency, they will be recompiled. However, export
# and runtime dependencies won't have recompiled so we need to
# propagate them to the parent app.
{dep_modules, _, _} =
fixpoint_runtime_modules(manifest_sources, Map.from_keys(dep_modules, true))

old_exports = Map.get(deps_exports, app, %{})

# Update exports
{exports, new_exports} =
for {module, _} <- dep_modules, reduce: {exports, []} do
{exports, new_exports} ->
export = exports_md5(module, false)

# If the exports are the same, then the API did not change,
# so we do not mark the export as stale. Note this has to
# be very conservative. If the module is not loaded or if
# the exports were not there, we need to consider it a stale
# export.
exports =
if export && old_exports[module] == export,
do: exports,
else: Map.put(exports, module, true)

# Then we store the new export if any
new_exports =
if export,
do: [{module, export} | new_exports],
else: new_exports

{exports, new_exports}
end

# Any dependency in old export but not in new export
# was removed so we need to mark them as stale too.
new_exports = Map.new(new_exports)
new_exports = Map.new(new_exports)

removed =
for {module, _} <- old_exports,
not is_map_key(new_exports, module),
do: {module, true},
into: %{}
removed =
for {module, _} <- old_exports,
not is_map_key(new_exports, module),
do: {module, true},
into: %{}

{Map.merge(stale_modules, removed), Map.merge(stale_exports, removed), new_exports}
modules = modules |> Map.merge(dep_modules) |> Map.merge(removed)
exports = Map.merge(exports, removed)
deps_exports = Map.put(deps_exports, app, new_exports)
{modules, exports, deps_exports}
end
end

defp fixpoint_runtime_modules(sources, modules) when modules != %{} do
4 changes: 2 additions & 2 deletions lib/mix/lib/mix/release.ex
Original file line number Diff line number Diff line change
@@ -67,7 +67,7 @@ defmodule Mix.Release do
@default_apps [kernel: :permanent, stdlib: :permanent, elixir: :permanent, sasl: :permanent]
@safe_modes [:permanent, :temporary, :transient]
@unsafe_modes [:load, :none]
@significant_chunks ~w(Atom AtU8 Attr Code StrT ImpT ExpT FunT LitT Line)c
@additional_chunks ~w(Attr)c
@copy_app_dirs ["priv"]

@doc false
@@ -879,7 +879,7 @@ defmodule Mix.Release do
@spec strip_beam(binary(), keyword()) :: {:ok, binary()} | {:error, :beam_lib, term()}
def strip_beam(binary, options \\ []) when is_list(options) do
chunks_to_keep = options[:keep] |> List.wrap() |> Enum.map(&String.to_charlist/1)
all_chunks = Enum.uniq(@significant_chunks ++ chunks_to_keep)
all_chunks = Enum.uniq(@additional_chunks ++ :beam_lib.significant_chunks() ++ chunks_to_keep)
compress? = Keyword.get(options, :compress, false)

case :beam_lib.chunks(binary, all_chunks, [:allow_missing_chunks]) do
2 changes: 1 addition & 1 deletion lib/mix/lib/mix/tasks/archive.build.ex
Original file line number Diff line number Diff line change
@@ -61,7 +61,7 @@ defmodule Mix.Tasks.Archive.Build do
project = Mix.Project.get()

if project && Keyword.get(opts, :compile, true) do
Mix.Task.run(:compile, args)
Mix.Task.run(:compile, ["--no-protocol-consolidation" | args])
end

source =
1 change: 1 addition & 0 deletions lib/mix/test/mix/tasks/archive_test.exs
Original file line number Diff line number Diff line change
@@ -32,6 +32,7 @@ defmodule Mix.Tasks.ArchiveTest do
message = "Generated archive \"archive-0.1.0.ez\" with MIX_ENV=dev"
assert_received {:mix_shell, :info, [^message]}
assert File.regular?(~c"archive-0.1.0.ez")
assert to_charlist(Mix.Project.consolidation_path()) not in :code.get_path()

assert_archive_content_default()
refute has_in_zip_file?(~c"archive-0.1.0.ez", ~c"archive-0.1.0/priv/.dot_file")
3 changes: 2 additions & 1 deletion lib/mix/test/mix/umbrella_test.exs
Original file line number Diff line number Diff line change
@@ -453,7 +453,8 @@ defmodule Mix.UmbrellaTest do
assert_received {:mix_shell, :info, ["Compiled lib/bar.ex"]}

# Recompiles if export dependency is removed
File.rm!("../foo/lib/foo.ex")
File.write!("../foo/lib/foo.ex", "")
ensure_touched("../foo/lib/foo.ex", "_build/dev/lib/bar/.mix/compile.elixir")
Mix.Task.clear()

ExUnit.CaptureIO.capture_io(:stderr, fn ->