Packages

An Elixir library for easily downloading and extracting Git repositories from various hosting services.

Current section

Files

Jump to
gitly lib utils fs.ex
Raw

lib/utils/fs.ex

defmodule Gitly.Utils.FS do
@moduledoc """
A module for file system operations.
This module provides utility functions for common file system operations
such as ensuring directories exist, moving files, and removing directories.
"""
@unix_root [
".",
"~",
"/",
"/usr",
"/usr/local",
"/var",
"/var/tmp",
"/tmp",
"/opt",
"/opt/local"
]
@windows_root [
"C:/",
"D:/",
"E:/",
"F:/",
"G:/",
"H:/",
"I:/",
"J:/",
"K:/",
"L:/",
"M:/",
"N:/",
"O:/",
"P:/",
"Q:/",
"R:/",
"S:/",
"T:/",
"U:/",
"V:/",
"W:/",
"X:/",
"Y:/",
"Z:/"
]
@doc """
Ensures that the directory for the given path exists.
Creates all necessary parent directories if they don't exist.
## Parameters
* `path` - The path for which to ensure the directory exists.
## Returns
* `:ok` if successful.
* `{:error, reason}` if an error occurs.
## Examples
iex> Gitly.Utils.FS.ensure_dir_exists("/tmp/new_dir/file.txt")
:ok
"""
@spec ensure_dir_exists(Path.t()) :: :ok | {:error, File.posix()}
def ensure_dir_exists(path), do: path |> Path.dirname() |> File.mkdir_p()
@doc """
Returns the root path for Gitly.
## Returns
* The path to the Gitly root directory.
## Examples
iex> Gitly.Utils.FS.root_path()
"/home/user/.gitly"
"""
@spec root_path() :: Path.t()
def root_path(), do: Path.join(System.user_home!(), ".gitly")
@doc """
Moves a file or directory from source to destination.
## Parameters
* `source` - The source path.
* `dest` - The destination path.
## Returns
* `{:ok, dest}` if successful.
* `{:error, reason}` if an error occurs.
## Examples
iex> Gitly.Utils.FS.move("/tmp/source", "/tmp/dest")
{:ok, "/tmp/dest"}
"""
@spec move(Path.t(), Path.t()) :: {:ok, Path.t()} | {:error, String.t()}
def move(source, dest) do
case File.rename(source, dest) do
:ok -> {:ok, dest}
{:error, reason} -> {:error, "Failed to move: #{inspect(reason)}"}
end
end
@doc """
Conditionally moves a file or directory.
## Parameters
* `source` - The source path.
* `dest` - The destination path.
* `condition` - Boolean condition determining whether to move.
## Returns
* `{:ok, dest}` if moved or if condition is false.
* `{:error, reason}` if an error occurs during move.
## Examples
iex> Gitly.Utils.FS.maybe_move("/tmp/source", "/tmp/dest", true)
{:ok, "/tmp/dest"}
iex> Gitly.Utils.FS.maybe_move("/tmp/source", "/tmp/dest", false)
{:ok, "/tmp/dest"}
"""
@spec maybe_move(Path.t(), Path.t(), boolean()) :: {:ok, Path.t()} | {:error, String.t()}
def maybe_move(source, dest, condition) when is_boolean(condition) do
if condition, do: move(source, dest), else: {:ok, dest}
end
@doc """
Conditionally removes a directory and all its contents.
## Parameters
* `path` - The path to remove.
* `condition` - Boolean condition determining whether to remove.
## Returns
* `{:ok, path}` if removed or if condition is false.
* `{:error, reason}` if an error occurs during removal.
## Examples
iex> Gitly.Utils.FS.maybe_rm_rf("/tmp/to_remove", true)
{:ok, "/tmp/to_remove"}
iex> Gitly.Utils.FS.maybe_rm_rf("/tmp/to_keep", false)
{:ok, "/tmp/to_keep"}
"""
@spec maybe_rm_rf(Path.t(), boolean()) :: {:ok, Path.t()} | {:error, String.t()}
def maybe_rm_rf(path, condition) when is_boolean(condition) do
if condition do
case File.rm_rf(path) do
{:ok, _} -> {:ok, path}
{:error, reason, _} -> {:error, "Failed to remove: #{inspect(reason)}"}
end
else
{:ok, path}
end
end
@doc """
Checks if a path is safe to remove.
Prevents removal of important system directories and non-existent paths.
## Parameters
* `dest` - The path to check.
## Returns
* `true` if the path is safe to remove.
* `false` otherwise.
## Examples
iex> Gitly.Utils.FS.rm?("/tmp/safe_to_remove")
true
iex> Gitly.Utils.FS.rm?("/")
false
"""
@spec rm?(Path.t()) :: boolean()
def rm?(dest),
do:
dest not in (@unix_root ++ @windows_root ++ [".."]) and
File.exists?(dest)
end