added error messages for posix error code
authorMaksim Pechnikov <parallel588@gmail.com>
Fri, 13 Nov 2020 12:13:14 +0000 (15:13 +0300)
committerMaksim Pechnikov <parallel588@gmail.com>
Fri, 13 Nov 2020 12:21:59 +0000 (15:21 +0300)
lib/pleroma/emoji/pack.ex
lib/pleroma/utils.ex
lib/pleroma/web/pleroma_api/controllers/emoji_file_controller.ex
lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex
priv/gettext/en/LC_MESSAGES/posix_errors.po [new file with mode: 0644]
priv/gettext/posix_errors.pot [new file with mode: 0644]

index ca58e543296b145a91ada6508a6ed0fb4e096f21..4f4e84bfe57ffe681770411bd995f0b5a636e58a 100644 (file)
@@ -22,14 +22,14 @@ defmodule Pleroma.Emoji.Pack do
 
   alias Pleroma.Emoji
   alias Pleroma.Emoji.Pack
+  alias Pleroma.Utils
 
   @spec create(String.t()) :: {:ok, t()} | {:error, File.posix()} | {:error, :empty_values}
   def create(name) do
     with :ok <- validate_not_empty([name]),
          dir <- Path.join(emoji_path(), name),
          :ok <- File.mkdir(dir) do
-      %__MODULE__{pack_file: Path.join(dir, "pack.json")}
-      |> save_pack()
+      save_pack(%__MODULE__{pack_file: Path.join(dir, "pack.json")})
     end
   end
 
@@ -94,7 +94,7 @@ defmodule Pleroma.Emoji.Pack do
   def add_file(%Pack{} = pack, _, _, %Plug.Upload{content_type: "application/zip"} = file) do
     with {:ok, zip_files} <- :zip.table(to_charlist(file.path)),
          [_ | _] = emojies <- unpack_zip_emojies(zip_files),
-         {:ok, tmp_dir} <- Pleroma.Utils.tmp_dir("emoji") do
+         {:ok, tmp_dir} <- Utils.tmp_dir("emoji") do
       try do
         {:ok, _emoji_files} =
           :zip.unzip(
@@ -282,18 +282,21 @@ defmodule Pleroma.Emoji.Pack do
     end
   end
 
-  @spec load_pack(String.t()) :: {:ok, t()} | {:error, :not_found}
+  @spec load_pack(String.t()) :: {:ok, t()} | {:error, :file.posix()}
   def load_pack(name) do
     pack_file = Path.join([emoji_path(), name, "pack.json"])
 
-    if File.exists?(pack_file) do
+    with {:ok, _} <- File.stat(pack_file),
+         {:ok, pack_data} <- File.read(pack_file) do
       pack =
-        pack_file
-        |> File.read!()
-        |> from_json()
-        |> Map.put(:pack_file, pack_file)
-        |> Map.put(:path, Path.dirname(pack_file))
-        |> Map.put(:name, name)
+        from_json(
+          pack_data,
+          %{
+            pack_file: pack_file,
+            path: Path.dirname(pack_file),
+            name: name
+          }
+        )
 
       files_count =
         pack.files
@@ -301,8 +304,6 @@ defmodule Pleroma.Emoji.Pack do
         |> length()
 
       {:ok, Map.put(pack, :files_count, files_count)}
-    else
-      {:error, :not_found}
     end
   end
 
@@ -434,10 +435,17 @@ defmodule Pleroma.Emoji.Pack do
     end
   end
 
-  defp from_json(json) do
+  defp from_json(json, attrs) do
     map = Jason.decode!(json)
 
-    struct(__MODULE__, %{files: map["files"], pack: map["pack"]})
+    pack_attrs =
+      attrs
+      |> Map.merge(%{
+        files: map["files"],
+        pack: map["pack"]
+      })
+
+    struct(__MODULE__, pack_attrs)
   end
 
   defp validate_shareable_packs_available(uri) do
@@ -491,10 +499,10 @@ defmodule Pleroma.Emoji.Pack do
   end
 
   defp create_subdirs(file_path) do
-    if String.contains?(file_path, "/") do
-      file_path
-      |> Path.dirname()
-      |> File.mkdir_p!()
+    with true <- String.contains?(file_path, "/"),
+         path <- Path.dirname(file_path),
+         false <- File.exists?(path) do
+      File.mkdir_p!(path)
     end
   end
 
@@ -518,10 +526,15 @@ defmodule Pleroma.Emoji.Pack do
 
   defp get_filename(pack, shortcode) do
     with %{^shortcode => filename} when is_binary(filename) <- pack.files,
-         true <- pack.path |> Path.join(filename) |> File.exists?() do
+         file_path <- Path.join(pack.path, filename),
+         {:ok, _} <- File.stat(file_path) do
       {:ok, filename}
     else
-      _ -> {:error, :doesnt_exist}
+      {:error, _} = error ->
+        error
+
+      _ ->
+        {:error, :doesnt_exist}
     end
   end
 
index e95766223d86e9965fbcfdc9f5595e98a5505461..fa75a8c9930426ae7f5473d7dc3c0ce0b2f3db9f 100644 (file)
@@ -3,6 +3,14 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Utils do
+  @posix_error_codes ~w(
+    eacces eagain ebadf ebadmsg ebusy edeadlk edeadlock edquot eexist efault
+    efbig eftype eintr einval eio eisdir eloop emfile emlink emultihop
+    enametoolong enfile enobufs enodev enolck enolink enoent enomem enospc
+    enosr enostr enosys enotblk enotdir enotsup enxio eopnotsupp eoverflow
+    eperm epipe erange erofs espipe esrch estale etxtbsy exdev
+  )a
+
   def compile_dir(dir) when is_binary(dir) do
     dir
     |> File.ls!()
@@ -44,4 +52,12 @@ defmodule Pleroma.Utils do
       error -> error
     end
   end
+
+  @spec posix_error_message(atom()) :: binary()
+  def posix_error_message(code) when code in @posix_error_codes do
+    error_message = Gettext.dgettext(Pleroma.Web.Gettext, "posix_errors", "#{code}")
+    "(POSIX error: #{error_message})"
+  end
+
+  def posix_error_message(_), do: ""
 end
index 428c97de62cf0619594ad7f0e1b5be81f4911fde..c15980ff0ead61ac3d9cd231da293366ce947062 100644 (file)
@@ -42,7 +42,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileController do
         |> json(%{error: "pack name, shortcode or filename cannot be empty"})
 
       {:error, _} = error ->
-        handle_error(conn, error, %{pack_name: pack_name})
+        handle_error(conn, error, %{
+          pack_name: pack_name,
+          message: "Unexpected error occurred while adding file to pack."
+        })
     end
   end
 
@@ -69,7 +72,11 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileController do
         |> json(%{error: "new_shortcode or new_filename cannot be empty"})
 
       {:error, _} = error ->
-        handle_error(conn, error, %{pack_name: pack_name, code: shortcode})
+        handle_error(conn, error, %{
+          pack_name: pack_name,
+          code: shortcode,
+          message: "Unexpected error occurred while updating."
+        })
     end
   end
 
@@ -84,7 +91,11 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileController do
         |> json(%{error: "pack name or shortcode cannot be empty"})
 
       {:error, _} = error ->
-        handle_error(conn, error, %{pack_name: pack_name, code: shortcode})
+        handle_error(conn, error, %{
+          pack_name: pack_name,
+          code: shortcode,
+          message: "Unexpected error occurred while deleting emoji file."
+        })
     end
   end
 
@@ -94,18 +105,24 @@ defmodule Pleroma.Web.PleromaAPI.EmojiFileController do
     |> json(%{error: "Emoji \"#{emoji_code}\" does not exist"})
   end
 
-  defp handle_error(conn, {:error, :not_found}, %{pack_name: pack_name}) do
+  defp handle_error(conn, {:error, :enoent}, %{pack_name: pack_name}) do
     conn
     |> put_status(:not_found)
     |> json(%{error: "pack \"#{pack_name}\" is not found"})
   end
 
-  defp handle_error(conn, {:error, _}, _) do
-    render_error(
-      conn,
-      :internal_server_error,
-      "Unexpected error occurred while adding file to pack."
-    )
+  defp handle_error(conn, {:error, error}, opts) do
+    message =
+      [
+        Map.get(opts, :message, "Unexpected error occurred."),
+        Pleroma.Utils.posix_error_message(error)
+      ]
+      |> Enum.join(" ")
+      |> String.trim()
+
+    conn
+    |> put_status(:internal_server_error)
+    |> json(%{error: message})
   end
 
   defp get_filename(%Plug.Upload{filename: filename}), do: filename
index a9accc5af76e0debe9dbf203acdcf4257dac5e70..2fb29d34e59d97d70852285718470587475c24fa 100644 (file)
@@ -71,7 +71,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
     with {:ok, pack} <- Pack.show(name: name, page: page, page_size: page_size) do
       json(conn, pack)
     else
-      {:error, :not_found} ->
+      {:error, :enoent} ->
         conn
         |> put_status(:not_found)
         |> json(%{error: "Pack #{name} does not exist"})
@@ -80,6 +80,17 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
         conn
         |> put_status(:bad_request)
         |> json(%{error: "pack name cannot be empty"})
+
+      {:error, error} ->
+        error_message =
+          add_posix_error(
+            "Failed to get the contents of the `#{name}` pack.",
+            error
+          )
+
+        conn
+        |> put_status(:internal_server_error)
+        |> json(%{error: error_message})
     end
   end
 
@@ -95,7 +106,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
             "Pack #{name} cannot be downloaded from this instance, either pack sharing was disabled for this pack or some files are missing"
         })
 
-      {:error, :not_found} ->
+      {:error, :enoent} ->
         conn
         |> put_status(:not_found)
         |> json(%{error: "Pack #{name} does not exist"})
@@ -116,10 +127,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
         |> put_status(:internal_server_error)
         |> json(%{error: "SHA256 for the pack doesn't match the one sent by the server"})
 
-      {:error, e} ->
+      {:error, error} ->
         conn
         |> put_status(:internal_server_error)
-        |> json(%{error: e})
+        |> json(%{error: error})
     end
   end
 
@@ -139,12 +150,16 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
         |> put_status(:bad_request)
         |> json(%{error: "pack name cannot be empty"})
 
-      {:error, _} ->
-        render_error(
-          conn,
-          :internal_server_error,
-          "Unexpected error occurred while creating pack."
-        )
+      {:error, error} ->
+        error_message =
+          add_posix_error(
+            "Unexpected error occurred while creating pack.",
+            error
+          )
+
+        conn
+        |> put_status(:internal_server_error)
+        |> json(%{error: error_message})
     end
   end
 
@@ -164,10 +179,12 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
         |> put_status(:bad_request)
         |> json(%{error: "pack name cannot be empty"})
 
-      {:error, _, _} ->
+      {:error, error, _} ->
+        error_message = add_posix_error("Couldn't delete the pack #{name}", error)
+
         conn
         |> put_status(:internal_server_error)
-        |> json(%{error: "Couldn't delete the pack #{name}"})
+        |> json(%{error: error_message})
     end
   end
 
@@ -180,12 +197,16 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
         |> put_status(:bad_request)
         |> json(%{error: "The fallback archive does not have all files specified in pack.json"})
 
-      {:error, _} ->
-        render_error(
-          conn,
-          :internal_server_error,
-          "Unexpected error occurred while updating pack metadata."
-        )
+      {:error, error} ->
+        error_message =
+          add_posix_error(
+            "Unexpected error occurred while updating pack metadata.",
+            error
+          )
+
+        conn
+        |> put_status(:internal_server_error)
+        |> json(%{error: error_message})
     end
   end
 
@@ -204,4 +225,10 @@ defmodule Pleroma.Web.PleromaAPI.EmojiPackController do
         |> json(%{error: "Error accessing emoji pack directory"})
     end
   end
+
+  defp add_posix_error(msg, error) do
+    [msg, Pleroma.Utils.posix_error_message(error)]
+    |> Enum.join(" ")
+    |> String.trim()
+  end
 end
diff --git a/priv/gettext/en/LC_MESSAGES/posix_errors.po b/priv/gettext/en/LC_MESSAGES/posix_errors.po
new file mode 100644 (file)
index 0000000..1ecaf8e
--- /dev/null
@@ -0,0 +1,141 @@
+## This file is a PO Template file.
+msgid "eperm"
+msgstr "Operation not permitted"
+
+msgid "eacces"
+msgstr "Permission denied"
+
+msgid "eagain"
+msgstr "Resource temporarily unavailable"
+  
+msgid "ebadf"
+msgstr "Bad file descriptor"
+  
+msgid "ebadmsg"
+msgstr "Bad message"
+  
+msgid "ebusy"
+msgstr "Device or resource busy"
+  
+msgid "edeadlk"
+msgstr "Resource deadlock avoided"
+  
+msgid "edeadlock"
+msgstr "Resource deadlock avoided"
+  
+msgid "edquot"
+msgstr "Disk quota exceeded"
+  
+msgid "eexist"
+msgstr "File exists"
+  
+msgid "efault"
+msgstr "Bad address"
+  
+msgid "efbig"
+msgstr "File too large"
+  
+msgid "eftype"
+msgstr "Inappropriate file type or format"
+  
+msgid "eintr"
+msgstr "Interrupted system call"
+  
+msgid "einval"
+msgstr "Invalid argument"
+  
+msgid "eio"
+msgstr "Input/output error"
+  
+msgid "eisdir"
+msgstr "Is a directory"
+  
+msgid "eloop"
+msgstr "Too many levels of symbolic links"
+  
+msgid "emfile"
+msgstr "Too many open files"
+  
+msgid "emlink"
+msgstr "Too many links"
+  
+msgid "emultihop"
+msgstr "Multihop attempted"
+  
+msgid "enametoolong"
+msgstr "File name too long"
+  
+msgid "enfile"
+msgstr "Too many open files in system"
+  
+msgid "enobufs"
+msgstr "No buffer space available"
+  
+msgid "enodev"
+msgstr "No such device"
+  
+msgid "enolck"
+msgstr "No locks available"
+  
+msgid "enolink"
+msgstr "Link has been severed"
+  
+msgid "enoent"
+msgstr "No such file or directory"
+  
+msgid "enomem"
+msgstr "Cannot allocate memory"
+  
+msgid "enospc"
+msgstr "No space left on device"
+  
+msgid "enosr"
+msgstr "Out of streams resources"
+  
+msgid "enostr"
+msgstr "Device not a stream"
+  
+msgid "enosys"
+msgstr "Function not implemented"
+  
+msgid "enotblk"
+msgstr "Block device required"
+  
+msgid "enotdir"
+msgstr "Not a directory"
+  
+msgid "enotsup"
+msgstr "Operation not supported"
+  
+msgid "enxio"
+msgstr "No such device or address"
+  
+msgid "eopnotsupp"
+msgstr "Operation not supported"
+  
+msgid "eoverflow"
+msgstr "Value too large for defined data type"
+  
+msgid "epipe"
+msgstr "Broken pipe"
+  
+msgid "erange"
+msgstr "Numerical result out of range"
+  
+msgid "erofs"
+msgstr "Read-only file system"
+  
+msgid "espipe"
+msgstr "Illegal seek"
+  
+msgid "esrch"
+msgstr "No such process"
+  
+msgid "estale"
+msgstr "Stale file handle"
+  
+msgid "etxtbsy"
+msgstr "Text file busy"
+  
+msgid "exdev"
+msgstr "Invalid cross-device link"
diff --git a/priv/gettext/posix_errors.pot b/priv/gettext/posix_errors.pot
new file mode 100644 (file)
index 0000000..c9f5939
--- /dev/null
@@ -0,0 +1,149 @@
+## This file is a PO Template file.
+##
+## `msgid`s here are often extracted from source code.
+## Add new translations manually only if they're dynamic
+## translations that can't be statically extracted.
+##
+## Run `mix gettext.extract` to bring this file up to
+## date. Leave `msgstr`s empty as changing them here as no
+## effect: edit them in PO (`.po`) files instead.
+msgid "eperm"
+msgstr ""
+
+msgid "eacces"
+msgstr ""
+
+msgid "eagain"
+msgstr ""
+  
+msgid "ebadf"
+msgstr ""
+  
+msgid "ebadmsg"
+msgstr ""
+  
+msgid "ebusy"
+msgstr ""
+  
+msgid "edeadlk"
+msgstr ""
+  
+msgid "edeadlock"
+msgstr ""
+  
+msgid "edquot"
+msgstr ""
+  
+msgid "eexist"
+msgstr ""
+  
+msgid "efault"
+msgstr ""
+  
+msgid "efbig"
+msgstr ""
+  
+msgid "eftype"
+msgstr ""
+  
+msgid "eintr"
+msgstr ""
+  
+msgid "einval"
+msgstr ""
+  
+msgid "eio"
+msgstr ""
+  
+msgid "eisdir"
+msgstr ""
+  
+msgid "eloop"
+msgstr ""
+  
+msgid "emfile"
+msgstr ""
+  
+msgid "emlink"
+msgstr ""
+  
+msgid "emultihop"
+msgstr ""
+  
+msgid "enametoolong"
+msgstr ""
+  
+msgid "enfile"
+msgstr ""
+  
+msgid "enobufs"
+msgstr ""
+  
+msgid "enodev"
+msgstr ""
+  
+msgid "enolck"
+msgstr ""
+  
+msgid "enolink"
+msgstr ""
+  
+msgid "enoent"
+msgstr ""
+  
+msgid "enomem"
+msgstr ""
+  
+msgid "enospc"
+msgstr ""
+  
+msgid "enosr"
+msgstr ""
+  
+msgid "enostr"
+msgstr ""
+  
+msgid "enosys"
+msgstr ""
+  
+msgid "enotblk"
+msgstr ""
+  
+msgid "enotdir"
+msgstr ""
+  
+msgid "enotsup"
+msgstr ""
+  
+msgid "enxio"
+msgstr ""
+  
+msgid "eopnotsupp"
+msgstr ""
+  
+msgid "eoverflow"
+msgstr ""
+  
+msgid "epipe"
+msgstr ""
+  
+msgid "erange"
+msgstr ""
+  
+msgid "erofs"
+msgstr ""
+  
+msgid "espipe"
+msgstr ""
+  
+msgid "esrch"
+msgstr ""
+  
+msgid "estale"
+msgstr ""
+  
+msgid "etxtbsy"
+msgstr ""
+  
+msgid "exdev"
+msgstr ""