From 494a4d76678bc3f0d5d0ebf502e362a90627fdd5 Mon Sep 17 00:00:00 2001 From: Jeff Kreeftmeijer Date: Tue, 25 Jun 2024 12:44:55 +0200 Subject: [PATCH] Handle binwrite failures in installer Since Elixir 1.16, the IO.binwrite/2 function no longer returns an :ok- or :error tuple. Instead, it simply raises an error when it fails. To keep compatibility with previous versions of Elixir, this patch implements binwrite_with_result, which is a delegate of IO.binwrite/2 on versions before 1.16, and a try-catch wrapper for Elixir 1.16 and above. With that function in place, the precious implementation is restored, which prints "Failure!" before the error message in the unlikely event that the write fails. --- lib/mix/tasks/appsignal.install.ex | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lib/mix/tasks/appsignal.install.ex b/lib/mix/tasks/appsignal.install.ex index fc536011..abad39f8 100644 --- a/lib/mix/tasks/appsignal.install.ex +++ b/lib/mix/tasks/appsignal.install.ex @@ -183,6 +183,15 @@ defmodule Mix.Tasks.Appsignal.Install do case File.open(appsignal_config_file_path(), [:write]) do {:ok, file} -> + case binwrite_with_result(file, appsignal_config_file_contents(config)) do + :ok -> + IO.puts("Success!") + + {:error, reason} -> + IO.puts("Failure! #{inspect(reason)}") + exit(:shutdown) + end + IO.binwrite(file, appsignal_config_file_contents(config)) IO.puts("Success!") File.close(file) @@ -193,6 +202,18 @@ defmodule Mix.Tasks.Appsignal.Install do end end + if Version.match?(System.version(), ">= 1.16.0") do + defp binwrite_with_result(path, contents) do + try do + IO.binwrite(path, contents) + catch + {:error, reason} -> {:error, reason} + end + end + else + defdelegate binwrite_with_result(path, contents), to: IO, as: :binwrite + end + # Link the config/appsignal.exs config file to the config/config.exs file. # If already linked, it's ignored. defp link_config_file do