Skip to content

Commit

Permalink
Add CI, remove warnings on Elixir v1.17-dev (#89)
Browse files Browse the repository at this point in the history
  • Loading branch information
josevalim authored Nov 9, 2023
1 parent 2219fa8 commit eab44e7
Show file tree
Hide file tree
Showing 16 changed files with 411 additions and 195 deletions.
3 changes: 3 additions & 0 deletions .formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[
inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"]
]
55 changes: 55 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: CI

on:
pull_request:
push:
branches:
- main

jobs:
test:
runs-on: ubuntu-20.04
env:
MIX_ENV: test
strategy:
fail-fast: false
matrix:
include:
- pair:
elixir: 1.12.4
otp: 23.3
- pair:
elixir: 1.15.7
otp: 26.1
lint: lint
steps:
- uses: actions/checkout@v3

- uses: erlef/setup-beam@v1
with:
otp-version: ${{matrix.pair.otp}}
elixir-version: ${{matrix.pair.elixir}}

- uses: actions/cache@v3
with:
path: |
deps
_build
key: ${{ runner.os }}-mix-${{matrix.pair.elixir}}-${{matrix.pair.otp}}-${{ hashFiles('**/mix.lock') }}
restore-keys: |
${{ runner.os }}-mix-
- run: mix deps.get

- run: mix format --check-formatted
if: ${{ matrix.lint }}

- run: mix deps.unlock --check-unused
if: ${{ matrix.lint }}

- run: mix deps.compile

- run: mix compile --warnings-as-errors
if: ${{ matrix.lint }}

- run: mix test
40 changes: 0 additions & 40 deletions .travis.yml

This file was deleted.

5 changes: 0 additions & 5 deletions config/config.exs

This file was deleted.

4 changes: 2 additions & 2 deletions lib/file_system.ex
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ defmodule FileSystem do
iex> FileSystem.subscribe(:worker)
"""
@spec start_link(Keyword.t) :: GenServer.on_start()
@spec start_link(Keyword.t()) :: GenServer.on_start()
def start_link(options) do
FileSystem.Worker.start_link(options)
end
Expand All @@ -55,7 +55,7 @@ defmodule FileSystem do
{:file_event, worker_pid, :stop}
"""
@spec subscribe(GenServer.server) :: :ok
@spec subscribe(GenServer.server()) :: :ok
def subscribe(pid) do
GenServer.call(pid, :subscribe)
end
Expand Down
48 changes: 31 additions & 17 deletions lib/file_system/backend.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ defmodule FileSystem.Backend do
def backend(backend) do
with {:ok, module} <- backend_module(backend),
:ok <- validate_os(backend, module),
:ok <- module.bootstrap
do
:ok <- module.bootstrap() do
{:ok, module}
else
{:error, reason} -> {:error, reason}
Expand All @@ -34,40 +33,55 @@ defmodule FileSystem.Backend do

defp backend_module(nil) do
case :os.type() do
{:unix, :darwin} -> :fs_mac
{:unix, :linux} -> :fs_inotify
{:unix, :freebsd} -> :fs_inotify
{:unix, :openbsd} -> :fs_inotify
{:win32, :nt} -> :fs_windows
system -> {:unsupported_system, system}
end |> backend_module
{:unix, :darwin} -> :fs_mac
{:unix, :linux} -> :fs_inotify
{:unix, :freebsd} -> :fs_inotify
{:unix, :openbsd} -> :fs_inotify
{:win32, :nt} -> :fs_windows
system -> {:unsupported_system, system}
end
|> backend_module
end
defp backend_module(:fs_mac), do: {:ok, FileSystem.Backends.FSMac}

defp backend_module(:fs_mac), do: {:ok, FileSystem.Backends.FSMac}
defp backend_module(:fs_inotify), do: {:ok, FileSystem.Backends.FSInotify}
defp backend_module(:fs_windows), do: {:ok, FileSystem.Backends.FSWindows}
defp backend_module(:fs_poll), do: {:ok, FileSystem.Backends.FSPoll}
defp backend_module(:fs_poll), do: {:ok, FileSystem.Backends.FSPoll}

defp backend_module({:unsupported_system, system}) do
Logger.error "I'm so sorry but `file_system` does NOT support your current system #{inspect system} for now."
Logger.error(
"I'm so sorry but `file_system` does NOT support your current system #{inspect(system)} for now."
)

{:error, :unsupported_system}
end

defp backend_module(module) do
functions = module.__info__(:functions)
{:start_link, 1} in functions &&
{:bootstrap, 0} in functions &&
{:supported_systems, 0} in functions ||

({:start_link, 1} in functions &&
{:bootstrap, 0} in functions &&
{:supported_systems, 0} in functions) ||
raise "illegal backend"
rescue
_ ->
Logger.error "You are using custom backend `#{inspect module}`, make sure it's a legal file_system backend module."
Logger.error(
"You are using custom backend `#{inspect(module)}`, make sure it's a legal file_system backend module."
)

{:error, :illegal_backend}
end

defp validate_os(backend, module) do
os_type = :os.type()

if os_type in module.supported_systems() do
:ok
else
Logger.error "The backend `#{backend}` you are using does NOT support your current system #{inspect os_type}."
Logger.error(
"The backend `#{backend}` you are using does NOT support your current system #{inspect(os_type)}."
)

{:error, :unsupported_system}
end
end
Expand Down
92 changes: 66 additions & 26 deletions lib/file_system/backends/fs_inotify.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,12 @@ defmodule FileSystem.Backends.FSInotify do

def bootstrap do
exec_file = executable_path()

if is_nil(exec_file) do
Logger.error "`inotify-tools` is needed to run `file_system` for your system, check https://github.com/rvoicilas/inotify-tools/wiki for more information about how to install it. If it's already installed but not be found, appoint executable file with `config.exs` or `FILESYSTEM_FSINOTIFY_EXECUTABLE_FILE` env."
Logger.error(
"`inotify-tools` is needed to run `file_system` for your system, check https://github.com/rvoicilas/inotify-tools/wiki for more information about how to install it. If it's already installed but not be found, appoint executable file with `config.exs` or `FILESYSTEM_FSINOTIFY_EXECUTABLE_FILE` env."
)

{:error, :fs_inotify_bootstrap_error}
else
:ok
Expand Down Expand Up @@ -74,32 +78,56 @@ defmodule FileSystem.Backends.FSInotify do
def parse_options(options) do
case Keyword.pop(options, :dirs) do
{nil, _} ->
Logger.error "required argument `dirs` is missing"
Logger.error("required argument `dirs` is missing")
{:error, :missing_dirs_argument}

{dirs, rest} ->
format = ["%w", "%e", "%f"] |> Enum.join(@sep_char) |> to_charlist

args = [
'-e', 'modify', '-e', 'close_write', '-e', 'moved_to', '-e', 'moved_from',
'-e', 'create', '-e', 'delete', '-e', 'attrib', '--format', format, '--quiet', '-m', '-r'
~c"-e",
~c"modify",
~c"-e",
~c"close_write",
~c"-e",
~c"moved_to",
~c"-e",
~c"moved_from",
~c"-e",
~c"create",
~c"-e",
~c"delete",
~c"-e",
~c"attrib",
~c"--format",
format,
~c"--quiet",
~c"-m",
~c"-r"
| dirs |> Enum.map(&Path.absname/1) |> Enum.map(&to_charlist/1)
]

parse_options(rest, args)
end
end

defp parse_options([], result), do: {:ok, result}

defp parse_options([{:recursive, true} | t], result) do
parse_options(t, result)
end

defp parse_options([{:recursive, false} | t], result) do
parse_options(t, result -- ['-r'])
parse_options(t, result -- [~c"-r"])
end

defp parse_options([{:recursive, value} | t], result) do
Logger.error "unknown value `#{inspect value}` for recursive, ignore"
Logger.error("unknown value `#{inspect(value)}` for recursive, ignore")
parse_options(t, result)
end

defp parse_options([h | t], result) do
Logger.error "unknown option `#{inspect h}`, ignore"
Logger.error("unknown option `#{inspect(h)}`, ignore")
parse_options(t, result)
end

Expand All @@ -112,21 +140,32 @@ defmodule FileSystem.Backends.FSInotify do

case parse_options(rest) do
{:ok, port_args} ->
bash_args = ['-c', '#{executable_path()} "$0" "$@" & PID=$!; read a; kill -KILL $PID']
bash_args = [
~c"-c",
~c"#{executable_path()} \"$0\" \"$@\" & PID=$!; read a; kill -KILL $PID"
]

all_args =
case :os.type() do
{:unix, :freebsd} ->
bash_args ++ ['--'] ++ port_args
bash_args ++ [~c"--"] ++ port_args

_ ->
bash_args ++ port_args
end

port = Port.open(
{:spawn_executable, '/bin/sh'},
[:binary, :stream, :exit_status, {:line, 16384}, {:args, all_args}, {:cd, System.tmp_dir!()}]
)
port =
Port.open(
{:spawn_executable, ~c"/bin/sh"},
[
:binary,
:stream,
:exit_status,
{:line, 16384},
{:args, all_args},
{:cd, System.tmp_dir!()}
]
)

Process.link(port)
Process.flag(:trap_exit, true)
Expand All @@ -138,18 +177,18 @@ defmodule FileSystem.Backends.FSInotify do
end
end

def handle_info({port, {:data, {:eol, line}}}, %{port: port}=state) do
def handle_info({port, {:data, {:eol, line}}}, %{port: port} = state) do
{file_path, events} = line |> parse_line
send(state.worker_pid, {:backend_file_event, self(), {file_path, events}})
{:noreply, state}
end

def handle_info({port, {:exit_status, _}}, %{port: port}=state) do
def handle_info({port, {:exit_status, _}}, %{port: port} = state) do
send(state.worker_pid, {:backend_file_event, self(), :stop})
{:stop, :normal, state}
end

def handle_info({:EXIT, port, _reason}, %{port: port}=state) do
def handle_info({:EXIT, port, _reason}, %{port: port} = state) do
send(state.worker_pid, {:backend_file_event, self(), :stop})
{:stop, :normal, state}
end
Expand All @@ -162,19 +201,20 @@ defmodule FileSystem.Backends.FSInotify do
{path, flags} =
case String.split(line, @sep_char, trim: true) do
[dir, flags, file] -> {Path.join(dir, file), flags}
[path, flags] -> {path, flags}
[path, flags] -> {path, flags}
end

{path, flags |> String.split(",") |> Enum.map(&convert_flag/1)}
end

defp convert_flag("CREATE"), do: :created
defp convert_flag("MOVED_TO"), do: :moved_to
defp convert_flag("DELETE"), do: :deleted
defp convert_flag("MOVED_FROM"), do: :moved_from
defp convert_flag("ISDIR"), do: :isdir
defp convert_flag("MODIFY"), do: :modified
defp convert_flag("CREATE"), do: :created
defp convert_flag("MOVED_TO"), do: :moved_to
defp convert_flag("DELETE"), do: :deleted
defp convert_flag("MOVED_FROM"), do: :moved_from
defp convert_flag("ISDIR"), do: :isdir
defp convert_flag("MODIFY"), do: :modified
defp convert_flag("CLOSE_WRITE"), do: :modified
defp convert_flag("CLOSE"), do: :closed
defp convert_flag("ATTRIB"), do: :attribute
defp convert_flag(_), do: :undefined
defp convert_flag("CLOSE"), do: :closed
defp convert_flag("ATTRIB"), do: :attribute
defp convert_flag(_), do: :undefined
end
Loading

0 comments on commit eab44e7

Please sign in to comment.