Current section
Files
Jump to
Current section
Files
lib/utils/archive/type.ex
defmodule Gitly.Utils.Archive.Type do
@moduledoc """
A module to handle archive types.
This module provides functions to work with various archive formats,
including zip, tar, tar.gz, tgz, tar.bz2, and tar.xz.
"""
@archive_extension_types %{
".zip" => :zip,
".tar" => :tar,
".tar.gz" => :tar_gz,
".tgz" => :tgz,
".tar.bz2" => :tar_bz2,
".tar.xz" => :tar_xz
}
@dotless_archive_extension_types %{
"zip" => :zip,
"tar" => :tar,
"tar.gz" => :tar_gz,
"tgz" => :tgz,
"tar.bz2" => :tar_bz2,
"tar.xz" => :tar_xz
}
@type ext :: :zip | :tar | :tar_gz | :tgz | :tar_bz2 | :tar_xz
@doc """
Checks if the given path is a valid archive.
## Parameters
* `path` - The file path to check.
## Returns
* `true` if the path ends with a valid archive extension, `false` otherwise.
## Examples
iex> Gitly.Utils.Archive.Type.valid?("example.zip")
true
iex> Gitly.Utils.Archive.Type.valid?("example.txt")
false
"""
@spec valid?(Path.t()) :: boolean()
def valid?(path),
do: Enum.any?(@archive_extension_types, fn {ext, _} -> String.ends_with?(path, ext) end)
@doc """
Returns the archive type as an atom from the given path.
## Parameters
* `path` - The file path to check.
## Returns
* The archive type as an atom (`:zip`, `:tar`, etc.) or `:unknown` if not recognized.
## Examples
iex> Gitly.Utils.Archive.Type.from_path("example.tar.gz")
:tar_gz
iex> Gitly.Utils.Archive.Type.from_path("example.txt")
:unknown
"""
@spec from_path(Path.t()) :: ext() | :unknown
def from_path(path) do
Enum.find_value(@archive_extension_types, :unknown, fn {ext, type} ->
if String.ends_with?(path, ext), do: type
end)
end
@doc """
Returns the archive type as an atom from the given string.
## Parameters
* `string` - The string representing the archive extension.
* `dot` - Whether the string includes a leading dot (default: true).
## Returns
* The archive type as an atom (`:zip`, `:tar`, etc.) or `:unknown` if not recognized.
## Examples
iex> Gitly.Utils.Archive.Type.from_string(".zip")
:zip
iex> Gitly.Utils.Archive.Type.from_string("tar.gz", false)
:tar_gz
iex> Gitly.Utils.Archive.Type.from_string("rar")
:unknown
"""
@spec from_string(binary(), boolean()) :: ext() | :unknown
def from_string(string, dot \\ true),
do:
if(dot,
do: Map.get(@archive_extension_types, string, :unknown),
else: Map.get(@dotless_archive_extension_types, string, :unknown)
)
@doc """
Returns the archive type as a string from the given type.
## Parameters
* `type` - The archive type as an atom.
* `dot` - Whether to include a leading dot in the result (default: true).
## Returns
* The archive extension as a string or `:unknown` if not recognized.
## Examples
iex> Gitly.Utils.Archive.Type.from_type(:zip)
".zip"
iex> Gitly.Utils.Archive.Type.from_type(:tar_gz, false)
"tar.gz"
iex> Gitly.Utils.Archive.Type.from_type(:unknown)
:unknown
"""
@spec from_type(ext(), boolean()) :: binary() | :unknown
def from_type(type, dot \\ true)
def from_type(:unknown, _dot), do: :unknown
def from_type(type, dot) when is_atom(type) do
case Enum.find(@archive_extension_types, fn {_ext, t} -> t == type end) do
{ext, _} -> if dot, do: ext, else: String.trim_leading(ext, ".")
nil -> :unknown
end
end
@doc """
Ensures the given extension has a leading dot.
## Parameters
* `ext` - The extension string.
## Returns
* The extension string with a leading dot.
## Examples
iex> Gitly.Utils.Archive.Type.ensure_leading_dot("zip")
".zip"
iex> Gitly.Utils.Archive.Type.ensure_leading_dot(".tar.gz")
".tar.gz"
"""
@spec ensure_leading_dot(binary()) :: binary()
def ensure_leading_dot(ext),
do: if(String.starts_with?(ext, "."), do: ext, else: ".#{ext}")
@doc """
Removes the leading dot from the given extension.
## Parameters
* `ext` - The extension string.
## Returns
* The extension string without a leading dot.
## Examples
iex> Gitly.Utils.Archive.Type.trim_leading_dot(".zip")
"zip"
iex> Gitly.Utils.Archive.Type.trim_leading_dot("tar.gz")
"tar.gz"
"""
@spec trim_leading_dot(binary()) :: binary()
def trim_leading_dot(ext),
do: if(String.starts_with?(ext, "."), do: String.trim_leading(ext, "."), else: ext)
@doc """
Removes the archive extension from the given path.
## Parameters
* `path` - The file path.
## Returns
* The path without the archive extension.
## Examples
iex> Gitly.Utils.Archive.Type.trim_extension("example.tar.gz")
"example"
iex> Gitly.Utils.Archive.Type.trim_extension("example.txt")
"example.txt"
"""
@spec trim_extension(Path.t()) :: Path.t()
def trim_extension(path) do
regex = ~r/\.(zip|tar|tar\.gz|tgz|tar\.bz2|tar\.xz)$/
if Regex.match?(regex, path), do: Regex.replace(regex, path, ""), else: path
end
end