-
Notifications
You must be signed in to change notification settings - Fork 0
Refactor Mix.Gleam
#1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,61 +3,77 @@ | |
|
|
||
| defmodule Mix.Gleam do | ||
| # Version that introduced `gleam export package-information` command | ||
| @required_gleam_version ">= 1.10.0" | ||
| @gleam_version_requirement ">= 1.10.0" | ||
|
|
||
| @spec load_config(Path.t()) :: config :: map() | ||
| def load_config(dir) do | ||
| File.cd!(dir, fn -> | ||
| gleam!(~W(export package-information --out /dev/stdout)) | ||
| |> JSON.decode!() | ||
| |> Map.fetch!("gleam.toml") | ||
| |> parse_config() | ||
| with {:ok, output} <- | ||
| gleam(~W(export package-information --out /dev/stdout)), | ||
| json <- JSON.decode!(output), | ||
| {:ok, gleam_toml} <- Map.fetch(json, "gleam.toml") do | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe? {{:ok, gleam_toml}, :fetch_toml} <- {Map.fetch(json, "gleam.toml"), :fetch_toml} do {:error, :fetch_toml} ->
{:error, "\"gleam.toml\" key not found in \"gleam export package-information\" output"}
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Initially i did that, but the only function that returns |
||
| parse_config(gleam_toml) | ||
| else | ||
| :error -> | ||
| {:error, "\"gleam.toml\" key not found in \"gleam export package-information\" output"} | ||
|
|
||
| {:error, message} -> | ||
| {:error, message} | ||
| end | ||
| |> assert_ok_value!() | ||
| end) | ||
| end | ||
|
|
||
| def parse_config(json) do | ||
| @spec parse_config(map()) :: {:ok, config :: map()} | {:error, message :: binary()} | ||
| def parse_config(json) when is_map(json) do | ||
| deps = | ||
| Map.get(json, "dependencies", %{}) | ||
| |> Enum.map(&parse_dep/1) | ||
| |> Enum.map(&parse_dep!/1) | ||
|
|
||
| dev_deps = | ||
| Map.get(json, "dev-dependencies", %{}) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Blocker imho:
Source: https://github.com/gleam-lang/gleam/blob/v1.15.0-rc1/CHANGELOG.md#build-tool ... AFAIU we must support |
||
| |> Enum.map(&parse_dep(&1, only: [:dev, :test])) | ||
|
|
||
| %{ | ||
| name: Map.fetch!(json, "name"), | ||
| version: Map.fetch!(json, "version"), | ||
| deps: deps ++ dev_deps | ||
| } | ||
| |> maybe_gleam_version(json) | ||
| |> maybe_erlang_opts(json["erlang"]) | ||
| rescue | ||
| KeyError -> | ||
| Mix.raise("Command \"gleam export package-information\" unexpected format: \n" <> json) | ||
| |> Enum.map(&parse_dep!(&1, only: [:dev, :test])) | ||
|
|
||
| with {:ok, name} <- Map.fetch(json, "name"), | ||
| {:ok, version} <- Map.fetch(json, "version") do | ||
| config = | ||
| %{ | ||
| name: name, | ||
| version: version, | ||
| deps: deps ++ dev_deps | ||
| } | ||
| |> maybe_gleam_version(json) | ||
| |> maybe_erlang_opts(json["erlang"]) | ||
|
|
||
| {:ok, config} | ||
| else | ||
| :error -> | ||
| {:error, | ||
| "Command \"gleam export package-information\" unexpected format: \n" <> | ||
| inspect(json, pretty: true, limit: :infinity)} | ||
| end | ||
| end | ||
|
|
||
| defp parse_dep({dep, requirement}, opts \\ []) do | ||
| dep = String.to_atom(dep) | ||
| defp parse_dep!({dep, requirement}, opts \\ []) do | ||
| String.to_atom(dep) | ||
| |> build_dep_spec(requirement, opts) | ||
| |> assert_ok_value!() | ||
| end | ||
|
|
||
| spec = | ||
| case requirement do | ||
| %{"version" => version} -> | ||
| {dep, version, opts} | ||
| defp build_dep_spec(dep, %{"version" => version}, []), | ||
| do: {:ok, {dep, version}} | ||
|
|
||
| %{"path" => path} -> | ||
| {dep, Keyword.merge(opts, path: Path.expand(path))} | ||
| defp build_dep_spec(dep, %{"version" => version}, opts), | ||
| do: {:ok, {dep, version, opts}} | ||
|
|
||
| %{"git" => git, "ref" => ref} -> | ||
| {dep, git: git, ref: ref} | ||
| defp build_dep_spec(dep, %{"path" => path}, opts), | ||
| do: {:ok, {dep, Keyword.merge(opts, path: Path.expand(path))}} | ||
|
|
||
| _ -> | ||
| Mix.raise("Gleam package #{dep} has unsupported requirement: #{inspect(requirement)}") | ||
| end | ||
| defp build_dep_spec(dep, %{"git" => git, "ref" => ref}, _opts), | ||
| do: {:ok, {dep, git: git, ref: ref}} | ||
|
|
||
| case spec do | ||
| {dep, version, []} -> {dep, version} | ||
| spec -> spec | ||
| end | ||
| end | ||
| defp build_dep_spec(dep, requirement, _opts), | ||
| do: {:error, "Gleam package #{dep} has unsupported requirement: #{inspect(requirement)}"} | ||
|
|
||
| defp maybe_gleam_version(config, json) do | ||
| case json["gleam"] do | ||
|
|
@@ -86,37 +102,58 @@ defmodule Mix.Gleam do | |
| Map.put(config, :application, application) | ||
| end | ||
|
|
||
| def require!() do | ||
| available_version() | ||
| |> Version.match?(@required_gleam_version) | ||
| @spec requirements!() :: :ok | ||
| def requirements!() do | ||
| case fetch_gleam_version() do | ||
| {:ok, gleam_version} -> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you still think a test is required, after the changes you made?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, in theory it should work, but so i theory it should have worked before the fix. Personally, since it's crucial I would test it. |
||
| if Version.match?(gleam_version, @gleam_version_requirement) do | ||
| {:ok, :ok} | ||
| else | ||
| {:error, | ||
| "Current Gleam version does not meet minimum requirements " <> | ||
| "#{@gleam_version_requirement}), got: #{gleam_version}"} | ||
| end | ||
|
|
||
| {:error, message} -> | ||
| {:error, message} | ||
| end | ||
| |> assert_ok_value!() | ||
| end | ||
|
|
||
| defp available_version do | ||
| case gleam!(["--version"]) do | ||
| "gleam " <> version -> Version.parse!(version) |> Version.to_string() | ||
| output -> Mix.raise("Command \"gleam --version\" unexpected format: #{output}") | ||
| defp fetch_gleam_version() do | ||
| case gleam(["--version"]) do | ||
| {:ok, version} -> | ||
| case Version.parse(version) do | ||
| {:ok, parsed_version} -> | ||
| {:ok, Version.to_string(parsed_version)} | ||
|
|
||
| :error -> | ||
| {:error, "Command \"gleam --version\" invalid version format: #{version}"} | ||
| end | ||
|
|
||
| {:error, output} -> | ||
| {:error, "Command \"gleam --version\" unexpected format: #{output}"} | ||
| end | ||
| rescue | ||
| e in Version.InvalidVersionError -> | ||
| Mix.raise("Command \"gleam --version\" invalid version format: #{e.version}") | ||
| end | ||
|
|
||
| defp gleam!(args) do | ||
| defp gleam(args) do | ||
| System.cmd("gleam", args) | ||
| catch | ||
| :error, :enoent -> | ||
| Mix.raise( | ||
| "The \"gleam\" executable is not available in your PATH. " <> | ||
| "Please install it, as one of your dependencies requires it. " | ||
| ) | ||
| {:error, | ||
| "The \"gleam\" executable is not available in your PATH. " <> | ||
| "Please install it, as one of your dependencies requires it"} | ||
| else | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have never seen def/catch/else syntax so far, unless I am blind it is also not mentioned here https://hexdocs.pm/elixir/try-catch-and-rescue.html But if it works, nvm.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Neither have I but seems to work. Maybe it its worth documenting this |
||
| {response, 0} -> | ||
| String.trim(response) | ||
| {:ok, String.trim(response)} | ||
|
|
||
| {response, _} when is_binary(response) -> | ||
| Mix.raise("Command \"gleam #{Enum.join(args, " ")}\" failed with reason: #{response}") | ||
| {:error, "Command \"gleam #{Enum.join(args, " ")}\" failed with reason: #{response}"} | ||
|
|
||
| {_, _} -> | ||
| Mix.raise("Command \"gleam #{Enum.join(args, " ")}\" failed") | ||
| {:error, "Command \"gleam #{Enum.join(args, " ")}\" failed"} | ||
| end | ||
|
|
||
| defp assert_ok_value!({:ok, term}), do: term | ||
| defp assert_ok_value!({:error, message}) when is_binary(message), do: Mix.raise(message) | ||
| end | ||
Uh oh!
There was an error while loading. Please reload this page.