diff --git a/lib/mix/lib/mix/local.ex b/lib/mix/lib/mix/local.ex index 2192e689f06..c6fc06fd466 100644 --- a/lib/mix/lib/mix/local.ex +++ b/lib/mix/lib/mix/local.ex @@ -232,40 +232,35 @@ defmodule Mix.Local do defp find_latest_eligible_version(entries, artifact_version) do elixir_version = Version.parse!(System.version()) + otp_release = System.otp_release() entries |> Enum.reverse() - |> find_version(artifact_version, elixir_version) + |> find_version(artifact_version, elixir_version, otp_release) end - defp find_version(entries, _artifact_version = nil, elixir_version) do - Enum.find_value(entries, &find_by_elixir_version(&1, elixir_version)) - end + defp find_version(entries, artifact_version, elixir_version, otp_release) do + entries = + if artifact_version do + Enum.filter(entries, &(hd(&1) == artifact_version)) + else + entries + end - defp find_version(entries, artifact_version, elixir_version) do - Enum.find_value(entries, &find_by_artifact_version(&1, artifact_version, elixir_version)) + Enum.find_value(entries, &find_by_elixir_version(&1, elixir_version, otp_release)) end - defp find_by_elixir_version([artifact_version, digest | versions], elixir_version) do - if version = Enum.find(versions, &(Version.compare(&1, elixir_version) != :gt)) do - {version, artifact_version, digest} - end - end - - defp find_by_artifact_version( - [artifact_version, digest | versions], - artifact_version, - elixir_version + defp find_by_elixir_version( + [artifact_version, digest, hex_elixir_version, hex_otp_release | _], + elixir_version, + otp_release ) do - if version = Enum.find(versions, &(Version.compare(&1, elixir_version) != :gt)) do - {version, artifact_version, digest} + if Version.compare(hex_elixir_version, elixir_version) != :gt and + hex_otp_release <= otp_release do + {hex_elixir_version, artifact_version, digest, hex_otp_release} end end - defp find_by_artifact_version(_entry, _artifact_version, _elixir_version) do - nil - end - ## Public keys @doc """ diff --git a/lib/mix/lib/mix/rebar.ex b/lib/mix/lib/mix/rebar.ex index 7f0b86c083d..2ecba673b59 100644 --- a/lib/mix/lib/mix/rebar.ex +++ b/lib/mix/lib/mix/rebar.ex @@ -49,12 +49,18 @@ defmodule Mix.Rebar do @doc """ Returns the path supposed to host the local copy of `rebar`. - The rebar3 installation is specific to the Elixir version, + The rebar3 installation is specific to the Elixir version and OTP release, in order to force updates when new Elixir versions come out. """ def local_rebar_path(:rebar3) do [major, minor | _] = String.split(System.version(), ".") - Path.join([Mix.Utils.mix_home(), "elixir", "#{major}-#{minor}", "rebar3"]) + + Path.join([ + Mix.Utils.mix_home(), + "elixir", + "#{major}-#{minor}-otp-#{System.otp_release()}", + "rebar3" + ]) end @doc """ diff --git a/lib/mix/lib/mix/tasks/local.hex.ex b/lib/mix/lib/mix/tasks/local.hex.ex index 2d43db67554..77a78bfa6e9 100644 --- a/lib/mix/lib/mix/tasks/local.hex.ex +++ b/lib/mix/lib/mix/tasks/local.hex.ex @@ -1,8 +1,8 @@ defmodule Mix.Tasks.Local.Hex do use Mix.Task - @hex_list_path "/installs/hex-1.x.csv" - @hex_archive_path "/installs/[ELIXIR_VERSION]/hex-[HEX_VERSION].ez" + @hex_list_path "/installs/hex.csv" + @hex_archive_path "/installs/[ELIXIR_VERSION]/hex-[HEX_VERSION]-otp-[OTP_RELEASE].ez" @shortdoc "Installs Hex locally" @@ -68,16 +68,13 @@ defmodule Mix.Tasks.Local.Hex do defp run_install(version, argv) do hex_url = Mix.Hex.url() - {elixir_version, hex_version, sha512} = - Mix.Local.find_matching_versions_from_signed_csv!( - "Hex", - version, - hex_url <> @hex_list_path - ) + {elixir_version, hex_version, sha512, otp_release} = + Mix.Local.find_matching_versions_from_signed_csv!("Hex", version, hex_url <> @hex_list_path) url = (hex_url <> @hex_archive_path) |> String.replace("[ELIXIR_VERSION]", elixir_version) + |> String.replace("[OTP_RELEASE]", otp_release) |> String.replace("[HEX_VERSION]", hex_version) # Unload the Hex module we loaded earlier to avoid conflicts when Hex is updated diff --git a/lib/mix/lib/mix/tasks/local.rebar.ex b/lib/mix/lib/mix/tasks/local.rebar.ex index 255ac4b9c55..0c6b02b9279 100644 --- a/lib/mix/lib/mix/tasks/local.rebar.ex +++ b/lib/mix/lib/mix/tasks/local.rebar.ex @@ -1,8 +1,8 @@ defmodule Mix.Tasks.Local.Rebar do use Mix.Task - @rebar3_list_url "/installs/rebar3-1.x.csv" - @rebar3_escript_url "/installs/[ELIXIR_VERSION]/rebar3-[REBAR_VERSION]" + @rebar3_list_url "/installs/rebar.csv" + @rebar3_escript_url "/installs/[ELIXIR_VERSION]/rebar3-[REBAR_VERSION]-otp-[OTP_RELEASE]" @shortdoc "Installs Rebar locally" @@ -110,13 +110,14 @@ defmodule Mix.Tasks.Local.Rebar do hex_url = Mix.Hex.url() list_url = hex_url <> list_url - {elixir_version, rebar_version, sha512} = + {elixir_version, rebar_version, sha512, otp_release} = Mix.Local.find_matching_versions_from_signed_csv!("Rebar", _version = nil, list_url) url = (hex_url <> escript_url) |> String.replace("[ELIXIR_VERSION]", elixir_version) |> String.replace("[REBAR_VERSION]", rebar_version) + |> String.replace("[OTP_RELEASE]", otp_release) install_from_path(manager, url, Keyword.put(opts, :sha512, sha512)) end diff --git a/lib/mix/test/mix/local_test.exs b/lib/mix/test/mix/local_test.exs index a1840487253..b3bc3e93045 100644 --- a/lib/mix/test/mix/local_test.exs +++ b/lib/mix/test/mix/local_test.exs @@ -3,67 +3,70 @@ Code.require_file("../test_helper.exs", __DIR__) defmodule Mix.LocalTest do use MixTest.Case - # openssl rsa -in elixirest.pem -pubout > elixirest.pub + # openssl rsa -in elixirtest.pem -pubout > elixirtest.pub @public_key """ -----BEGIN PUBLIC KEY----- - MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA37moKP1dGGLhsP3d8Fwv - W25SoYZUY2K+Iq7A0OBV36Rnb8yW3BWjfh5YtmPvUCfYUbNCW2HTMMgBntkQ4YmN - B9tHVZazl2uX9lGCfZZPFc/9umvKRojCPkMN81MfTxqnY0oaLHr6DB86RsWHB+ld - 782Xf+nd9q3LFdUl8SGlKX7uzfVWd4EWYNcL7aLeLSupZWeNg8uVmY3zua0EgIlQ - XryalIOZb/R+pwprWZoftCl+20FGYi/mJpo/idFtXsR0sJKF4X0W3NORT9RIRbs9 - WdjiFi+eIP7Nm8KSF4pbaXCqSmVf9cgvUuGTxc9/P5GcIPAlkcsSrE5peLyUCk5f - 2QIDAQAB + MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkIaIn8uhwSVp9d+aV+GL + tFjMt0TylxDu6x5jwjDvXCD3Of6VAriqcdXDJAqGPN1C4HNTxfihYpLZB+qXCNQM + oEa/I1h6OB5CXb8zIOl2Yriforr9LS+EkP+1xVmz7w7lNAagD0rJyJrTDbYDV+2Y + EnRq84FpZc/+7z6ojc3RMh9x/5t9jDE4Ft3NCujCmGsy2AcBlMpAQkcNveyplNmu + fZH2vId8h8t6rABwEZgSazHObkcHwE3bndynFO7zXvBu6ebNUDuU3DrDJ1Iepy9I + jEuZ6h13j7hL5l+j+9bGRQtasWgwvCkCGD+/2Lz4Ehox58voDCzAK09rsCwQ6gAT + CQIDAQAB -----END PUBLIC KEY----- """ - # openssl genrsa -aes256 -out elixirtest.pem -passout stdin 2048 + # openssl genrsa -aes256 -out elixirtest.pem -passout pass:secret12 2048 @private_key """ - -----BEGIN RSA PRIVATE KEY----- - Proc-Type: 4,ENCRYPTED - DEK-Info: AES-256-CBC,48BA5153DA2F120ECE063B33C1204A49 - - 5gp3daNWujH7o9S/dJQEt9TYTRP0pPZtU55PlZrzWt52optr7XHW/ENOm84g5J70 - QCPELp12jfQsNiPwbVWXKy2zD3QlNiAelf65hqLWJTWli7XIXfdP46VXOu67OKf9 - Ziw4HQ+AdBEwFt20wJst77iy17sNlyxp5DhNDonnSizzIowgUAJkoNI5aBUU6D8X - KTSIftZW35Z4SudkazdoHepEfItZTI8mB4rvfn71Q4oOBA1rAuUUmdPWoPBfUHDa - hvIp2T2Q8zZYqm0+SjDxZUYOOreE7fuf5NSLhHHt7+jyWQmtaVxnOWms72G+9xT0 - NGmOEB0WEg1kBsUbYOXXwyCAZhNA6MaKCtgjQczRTK+geS1xNaFc9FDEk3ZjN4Z8 - PxrKQoqo+2aQGVcatZWCom80Dci3bIv7iZNA/y1rjfBn+MeitMOGscP7/CBrJAbI - bh1mvCu0McSnqlN0a+EuCVfJQYFMzjibpRVzKAST0QeaxXd5QxHfcPFPBLOpiVWc - NjHaZsHORyoJbUKGA4rgOiSB63mv7SDRA2mvxWpwV/+6MuwBah6t6CGoEsAr1Hbn - 1ySt5w27bw3QEf2KTiuxDubo8UrF0eYzP5A9MH8vRpSRZHg8T3SBVfPJ/pM16Lnn - 5BaMUdxDFJeet5HUYoke9Zm3udh2BvwGiKhzc9Pbw/EcsCcvChMimRTasqTaRf+S - uIm0Un7o+7kTuvBo2y87j2urCEUzft5QqEynbkR7p3vZnwoLLj+supXh3V8ivW4s - Z6ql+ukRcWd/ode+lbSiYfAJCLc1tCqJ3kTnMnADJBlL0TX7YnwBwWuwwPuZgeAv - F6nnBE1SBQ1WK+bjSVzIqmNFqsZw34wgpnz2heX0q8msF5pzd6EIeA+uz86k8XYh - 4eVZYGXxa4Exodh/MqEpRuN1ytWDXvHULh0gml7xwZC3R50UD8uBNt5RGjXUkjXc - V0atKuvgzVlsB4xbDhVP7EVYHBF02NfNOsvo7kh0Yl1IcT/42UaCGYuU1o9zotPv - 9b3SHz/HOmBVj2uCdR5XZ4EolP5Iv9vqIDt9DsuDpOyO+AFOww0FnJNCQ1Hmfb0T - qBYPv994oSPYLCGR4a8i/xfmmV8KbAIVEgK3AMbz8RxKr3WBWXWnzQdr4+y4EG24 - hSnR52XQ42edv/fkqf9ez+fKNQ9i7PtlPE96Q21NeLMNKHh43X8hJFDh+oPz3Aio - YSNMCZnoyRdrjBRCsVBpnyoLmuhWwG9RlcrEj3G0BxYPh/weaBOAKAHjSr28yuUj - yIa8uddszC6XHSiVUgu7SGO8gQmq++eNdckjX/pEug5MjcWLUqaUg6+YLFWY6NLf - uDPOYuivq7ErtKTvP2xl3TBEDKhdfqxA2+RFxbBDmKjffZnRkcknQsxhlzAdbg22 - Jwa2B1nrfjJpX5F+1Av2jHQGbIKMqZzv8fo1binMKpptFzokbWEOjcPCb3tPuomG - ZRkW3qO2pdyYX2N7VXYG9tGi2HrN/oFrWnHPoYF23v85V8WxNkODOCpTz85e6R5v - PVu+FCNFj5weEOTRhtEQyJo7mU5qIRwYeZvVxiC6W+XeFs95wdBE/Lvpg8yZ8D9d - -----END RSA PRIVATE KEY----- + -----BEGIN ENCRYPTED PRIVATE KEY----- + MIIFNTBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQjNQQlREZJuQveXPa + 0ACpEwICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEFoBWTpEyO8y6xdG + fuud2AIEggTQDQRXrxBpj1yIbnLcP7i43Gat2tEM+XXkvqbzwL+CdjfEzaqiBGwc + FEyWnJj5hENWtNq/AAwzcEALa3QdLJ2W+tX/hc5r1vILpy2oW0vPKfv4yadNyPWq + UzolKKU3MbREP4KXsuAVYepolRWAcWSZKozYBm9HUPwsSyM6E9K0aWmNr/YBbZPE + UEA949Pq6buQvwT2Gj/6FQlutEvJMuY8woM2I/RKSVHeSoB8FWJGSNd7ZY2DN7DG + o6kmhK0OVjxx0SYQwUm++4gh3yFRX6vnTf8ZADOwCOJE/hjMfqivNelJHGojYAD2 + 0c3zdo0HGvVghg2bzUxhc0HJqUFiUDNW1W3AVBrUJiQgHQb/ENYaMrd6klrslHDV + cnPkz+dZAq/WC3KFqufkSmHxU97dDs9G6hKdm80JVEdPG4aMJvHzVL6SvS+g/e7r + IJGZCFGch9SbikmESKegIfyLJYQrfjuLdXWPHx9J+LAmtRTA1xPwLH/aqCr9ahBB + JCl4RaezF0BH2GYLAV+Ailpy2jqsC3v9RW8vpQmU227H8ERFu9ZcWhZITbRhbjRB + oh3ERnOmvU3VWIXQ0j1cm9Qjl52y8HZJxef2dYsW8nmTSRj32gi9UnEsyOFL9FB7 + KcFDq6o+go4nIfsmaAEOF1Hh01JZkbuX1SgmHvGRbNksTuljP/XZn7Wzz7fTcVZR + NsTgMbBl1+ctDHUBT7YzsHeEx8tZvLPDP8lO23aEnmRb6bHD4hVorUEM/kOpSm6g + DNP0buYGEAu4rZrp+5s46Y/RVAIhU4+663jqzmbmwOwEcuOJJCJn8eUGVweAgWX3 + 1PQTfpkk7RLxxuLeMHxEIynxyZNpSgfX0VGKe5UtplwcTQL8VgeZHayDxnhFwtSm + lBfPIM/i4kj7RonuehyPjuBA6n1CyqRVqc49c/3kVMgovqvbUQxQ7TtSfzfkhVyV + yRnRxcek+6Gctoahas5DPQl7y8jnwgg5qvUjYo6GIwBoxLUzIw+0MBn7gdMYHNmh + Xd9XZpRilAMJF5ynr2QyaE95XaQ3yK62FPgmIDdzfnN7es169O4SiXsgUyaSWsx9 + VxOHP4r0j6epWLH4W11MQEj4Bb8wG//pCD5Kz2xvwhWaKjkqzuqGDaXSOTKV0FQM + NG5GbNNELNCy/ocvlsaC+acWcOfsx4f6yovCGVTpTr+wjbDqd1kEBoRTuyTPY+6P + 0OU1Vf2GpMA2NDw0ZUOAllGVLrgD+326bu7ipePgiT8SiPNNsagMJNCSk5d3C4+K + bc0hakF/MIjPs3a+5/2mwtxk3QYYCIHITN8SIj+kFd7WMXALyClgWt3tcKwLTgMa + BSatAvwsoi2kiBu2A49msvka7YD8fENhtUl8vU12ZZdTih1chyPDifgfRgOfkZFW + a1XiLKjnWqeBqvJ3hBKuXweN6P7nvZidBYSESl3yrM00pA97Eta2in7ok80MRYH3 + bsqzC636h43Mu8PbTKGpK66j1ts6uY9YONAGfGCcfj/wyBWuqNViv7vK38th8wj8 + AG4rKyIlKxbFwo4Oh3jZTbfVF1Azl8pr0rK2P3W/EhfvWIrZVfB4Upy0wL6MjysE + RZ/57N2wFq4KBb9x9hCMFxignWmgyzPK+1J0iPRkSmpn9P/SzywDBIg= + -----END ENCRYPTED PRIVATE KEY----- """ @csv """ - 1.2.5,ABC,0.9.0 - 1.2.3,DEF,1.0.0 - 1.2.4,GHI,1.0.0 + 1.2.5,ABC,0.9.0,25 + 1.2.5,ABC,0.9.0,26 + 1.2.3,DEF,1.0.0,25 + 1.2.3,DEF,1.0.0,26 + 1.2.4,GHI,1.0.0,25 + 1.2.4,GHI,1.0.0,26 """ # openssl dgst -sha512 -sign elixirtest.pem hex-1.x.csv | openssl base64 > elixirtest.csv.signed @csv_signed """ - VRydmXOdEXQcKJu/SK/nKnE00T+s/T4mpXrYROMSXhD/s8ClvdimnGg61ie3YBS6 - LXOjlEhbtMHRM2rTOUvv4z7FcyzwvSxSjunlVi2g3c1pVOZ78MonnYhGb44tZw/q - SOVmV+jJhc9EZFMIAAM3plMoyssyw2pMh7ZB/DxCQTIem3Qf0Ujzc2bYkLVlw7R+ - 1Rn6dcYEgCzyldVkAUMaYBwieyweWALA+YVDCMudJJK2J7p1OnuoPSVV+N3OkB/Z - T6Jj5ljD+54XnuxAMcgCoF9lpOwXscnw/Ma+8JqIoWo0jNFE3ji+8dGCUzQUdSe8 - llLXgJJE2tGpDhEXBA3idg== + CVkhTiuCAfooYPhjyynDq40QhmDwLAEJvpwYytPCf6mpLXVrLXo/d/A2L8iBRJVx + uk4PNVksLRZ1ChBzGFvEqaFjrH+ndQAYLbwqcaMIn743YNUjGNVfTZkU47nBybtJ + BwDSBaAsow0Iitsl+UkDN/QvVoOLiX/x2cpnwCMrCgbTMroTzhH07vfLo3uCf8iY + cncImd07ffCewt77AsVPpKgJNOLzn+EBnvh4LbGWQya8EkgyQKuMBuNU86MYtFiW + NVpR7vbvqgWpEyr1XeknxKkhzYpna3+irXdMxGZw65WvFNWGJKnpuBTNHnHL+wX8 + oNQLUfakH8/VMV/8v6Irbg== """ # We don't actually use it but it exists for documentation purposes. @@ -83,8 +86,10 @@ defmodule Mix.LocalTest do File.write!("csv", @csv) File.write!("csv.signed", @csv_signed) - assert {"1.0.0", "1.2.4", "GHI"} = + assert {"1.0.0", "1.2.4", "GHI", otp_release} = Mix.Local.find_matching_versions_from_signed_csv!("name", nil, "csv") + + assert otp_release <= System.otp_release() end) end @@ -94,12 +99,16 @@ defmodule Mix.LocalTest do File.write!("csv", @csv) File.write!("csv.signed", @csv_signed) - assert {"0.9.0", "1.2.5", "ABC"} = + assert {"0.9.0", "1.2.5", "ABC", otp_release} = Mix.Local.find_matching_versions_from_signed_csv!("name", "1.2.5", "csv") - assert {"1.0.0", "1.2.3", "DEF"} = + assert otp_release <= System.otp_release() + + assert {"1.0.0", "1.2.3", "DEF", otp_release} = Mix.Local.find_matching_versions_from_signed_csv!("name", "1.2.3", "csv") + assert otp_release <= System.otp_release() + assert_raise Mix.Error, "Could not find a version of name matching: 1.3.0", fn -> Mix.Local.find_matching_versions_from_signed_csv!("name", "1.3.0", "csv") end @@ -109,7 +118,9 @@ defmodule Mix.LocalTest do @tag :tmp_dir test "raise on bad signature", %{tmp_dir: tmp_dir} do File.cd!(tmp_dir, fn -> - csv_signed = String.replace(@csv_signed, "VRy", "BAD") + <<_, _, _>> <> rest = @csv_signed + csv_signed = "BAD" <> rest + File.write!("csv", @csv) File.write!("csv.signed", csv_signed) diff --git a/lib/mix/test/test_helper.exs b/lib/mix/test/test_helper.exs index 0fc0abc486e..e80be357cc0 100644 --- a/lib/mix/test/test_helper.exs +++ b/lib/mix/test/test_helper.exs @@ -254,7 +254,8 @@ end rebar3_source = System.get_env("REBAR3") || Path.expand("fixtures/rebar3", __DIR__) [major, minor | _] = String.split(System.version(), ".") -rebar3_target = Path.join([mix, "elixir", "#{major}-#{minor}", "rebar3"]) +version_dir = "#{major}-#{minor}-otp-#{System.otp_release()}" +rebar3_target = Path.join([mix, "elixir", version_dir, "rebar3"]) File.mkdir_p!(Path.dirname(rebar3_target)) File.cp!(rebar3_source, rebar3_target)