This repository has been archived by the owner on Oct 8, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
191 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
defmodule Xgit.Core.FileMode do | ||
@moduledoc ~S""" | ||
Describes the file type as represented on disk. | ||
""" | ||
|
||
@typedoc ~S""" | ||
An integer describing the file type as represented on disk. | ||
Git uses a variation on the Unix file permissions flags to denote a file's | ||
intended type on disk. The following values are recognized: | ||
* `0o100644` - normal file | ||
* `0o100755` - executable file | ||
* `0o120000` - symbolic link | ||
* `0o040000` - tree (subdirectory) | ||
* `0o160000` - submodule (aka gitlink) | ||
This module is intended to be `use`d. Doing so will create an `alias` to the module | ||
so as to make `FileMode.t` available for typespecs and will `import` the | ||
`is_file_mode/1` guard. | ||
""" | ||
@type t :: 0o100644 | 0o100755 | 0o120000 | 0o040000 | 0o160000 | ||
|
||
@doc "Mode indicating an entry is a tree (aka directory)." | ||
@spec tree :: t | ||
def tree, do: 0o040000 | ||
|
||
@doc "Mode indicating an entry is a symbolic link." | ||
@spec symlink :: t | ||
def symlink, do: 0o120000 | ||
|
||
@doc "Mode indicating an entry is a non-executable file." | ||
@spec regular_file :: t | ||
def regular_file, do: 0o100644 | ||
|
||
@doc "Mode indicating an entry is an executable file." | ||
@spec executable_file :: t | ||
def executable_file, do: 0o100755 | ||
|
||
@doc "Mode indicating an entry is a submodule commit in another repository." | ||
@spec gitlink :: t | ||
def gitlink, do: 0o160000 | ||
|
||
@doc "Return `true` if the file mode represents a tree." | ||
@spec tree?(file_mode :: term) :: boolean | ||
def tree?(file_mode) | ||
def tree?(0o040000), do: true | ||
def tree?(_), do: false | ||
|
||
@doc "Return `true` if the file mode a symbolic link." | ||
@spec symlink?(file_mode :: term) :: boolean | ||
def symlink?(file_mode) | ||
def symlink?(0o120000), do: true | ||
def symlink?(_), do: false | ||
|
||
@doc "Return `true` if the file mode represents a regular file." | ||
@spec regular_file?(file_mode :: term) :: boolean | ||
def regular_file?(file_mode) | ||
def regular_file?(0o100644), do: true | ||
def regular_file?(_), do: false | ||
|
||
@doc "Return `true` if the file omde represents an executable file." | ||
@spec executable_file?(file_mode :: term) :: boolean | ||
def executable_file?(file_mode) | ||
def executable_file?(0o100755), do: true | ||
def executable_file?(_), do: false | ||
|
||
@doc "Return `true` if the file mode represents a submodule commit in another repository." | ||
@spec gitlink?(file_mode :: term) :: boolean | ||
def gitlink?(file_mode) | ||
def gitlink?(0o160000), do: true | ||
def gitlink?(_), do: false | ||
|
||
@doc ~S""" | ||
Return `true` if the value is one of the known file mode values. | ||
""" | ||
@spec valid?(term) :: boolean | ||
def valid?(0o040000), do: true | ||
def valid?(0o120000), do: true | ||
def valid?(0o100644), do: true | ||
def valid?(0o100755), do: true | ||
def valid?(0o160000), do: true | ||
def valid?(_), do: false | ||
|
||
@valid_file_modes [0o100644, 0o100755, 0o120000, 0o040000, 0o160000] | ||
|
||
@doc ~S""" | ||
This guard requires the value to be one of the known git file mode values. | ||
""" | ||
defguard is_file_mode(t) when t in @valid_file_modes | ||
|
||
defmacro __using__(opts) do | ||
quote location: :keep, bind_quoted: [opts: opts] do | ||
alias Xgit.Core.FileMode | ||
import Xgit.Core.FileMode, only: [is_file_mode: 1] | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
defmodule Xgit.Core.FileModeTest do | ||
use ExUnit.Case, async: true | ||
|
||
use Xgit.Core.FileMode | ||
|
||
test "tree/0" do | ||
assert FileMode.tree() == 0o040000 | ||
end | ||
|
||
test "symlink/0" do | ||
assert FileMode.symlink() == 0o120000 | ||
end | ||
|
||
test "regular_file/0" do | ||
assert FileMode.regular_file() == 0o100644 | ||
end | ||
|
||
test "executable_file/0" do | ||
assert FileMode.executable_file() == 0o100755 | ||
end | ||
|
||
test "gitlink/0" do | ||
assert FileMode.gitlink() == 0o160000 | ||
end | ||
|
||
test "tree?/1" do | ||
assert FileMode.tree?(FileMode.tree()) | ||
refute FileMode.tree?(FileMode.tree() + 1) | ||
end | ||
|
||
test "symlink?/1" do | ||
assert FileMode.symlink?(FileMode.symlink()) | ||
refute FileMode.symlink?(FileMode.symlink() + 1) | ||
end | ||
|
||
test "regular_file?/1" do | ||
assert FileMode.regular_file?(FileMode.regular_file()) | ||
refute FileMode.regular_file?(FileMode.regular_file() + 1) | ||
end | ||
|
||
test "executable_file?/1" do | ||
assert FileMode.executable_file?(FileMode.executable_file()) | ||
refute FileMode.executable_file?(FileMode.executable_file() + 1) | ||
end | ||
|
||
test "gitlink?/1" do | ||
assert FileMode.gitlink?(FileMode.gitlink()) | ||
refute FileMode.gitlink?(FileMode.gitlink() + 1) | ||
end | ||
|
||
test "valid?/1" do | ||
assert FileMode.valid?(FileMode.tree()) | ||
refute FileMode.valid?(FileMode.tree() + 1) | ||
|
||
assert FileMode.valid?(FileMode.symlink()) | ||
refute FileMode.valid?(FileMode.symlink() + 1) | ||
|
||
assert FileMode.valid?(FileMode.regular_file()) | ||
refute FileMode.valid?(FileMode.regular_file() + 1) | ||
|
||
assert FileMode.valid?(FileMode.executable_file()) | ||
refute FileMode.valid?(FileMode.executable_file() + 1) | ||
|
||
assert FileMode.valid?(FileMode.gitlink()) | ||
refute FileMode.valid?(FileMode.gitlink() + 1) | ||
end | ||
|
||
@valid_file_modes [0o040000, 0o120000, 0o100644, 0o100755, 0o160000] | ||
|
||
defp accepted_file_mode?(t) when is_file_mode(t), do: true | ||
defp accepted_file_mode?(_), do: false | ||
|
||
describe "is_file_mode/1" do | ||
test "accepts known file modes" do | ||
for t <- @valid_file_modes do | ||
assert accepted_file_mode?(t) | ||
end | ||
end | ||
|
||
test "rejects invalid values" do | ||
refute accepted_file_mode?(:mumble) | ||
refute accepted_file_mode?(0) | ||
refute accepted_file_mode?(1) | ||
refute accepted_file_mode?(0o100645) | ||
refute accepted_file_mode?("blob") | ||
refute accepted_file_mode?('blob') | ||
refute accepted_file_mode?(%{blob: true}) | ||
refute accepted_file_mode?({:blob}) | ||
refute accepted_file_mode?(fn -> :blob end) | ||
refute accepted_file_mode?(self()) | ||
end | ||
end | ||
end |