Consider support fswatch
josevalim opened this issue · 23 comments
fswatch
supports unix, freebsd and mac, so it looks like a nice alternative. I am posting it here in case someone wants to tackle it: https://github.com/emcrisostomo/fswatch
I will take a look closely after finishing my trip.
While it longs, I'm just saying Hello from Tibet :-)
FreeBSD user here .. I would really like to have this, too :)
Cheers
Oh hai!
I see https://github.com/Vagabond/erl_kqueue
Or there is better/smaller filesystem watching API ?
UPD. I added basic freebsd
compilation and bsd
running support but it should be finished.
@josevalim I reviewed fswatch
. I'd better support everything that users of elixir
and erlang
is using. I just don't want to throw away our backends. They are cute. From the other side fs
won't rely on anything, we have freedom.
+1
I started developing on freebsd as well (phoenix) and no support for code reloading is a bit problematic. Any ETA on this fix? I can provide help with testing if needed.
Found the following error in FreeBSD 11.0-BETA2 with Erlang/OTP 19.0.2 and Elixir 1.3.2 running Phoenix 1.2.0:
[error] fs does not support the current operating system
Is the error message above benign?
(I've been redirected to here from phoenixframework/phoenix#920 )
@jj1bdx basically you won't get live reload if you do development under FreeBSD for now. I have not been affected in production.
I've added rudimentary support for fswatch (it becoming the only backend) in erlfsmon. Take a look, perhaps the backend could be similarly used in fs (I haven't tested it anywhere but osx, it uses the ).sh -c '$0; read; kill'
trick, so i'm not sure how this will work out on windows
@proger Any update on this issue? Maybe I can help if you give me some context? (I am a bit lost as to what exactly has to be done)
This is the only thing preventing me from developing on FreeBSD via SSH from windows.
@kuon As a temporary fix, try to make the inotify support work using https://github.com/wulf7/libinotify-kqueue shim. fs might needs some patches to work.
To this issue: Making a proper kqueue/kevent backend is the best way to go. Less brittle at the expense of duplicating some effort. Ancedotal evidence: our team once had to rip out a fsevent file notification monitor backend in another language that communicated with an external process because it leaked those processes and wasted METRIC TONS of resources, slowing down development.
@steakknife If we are going to throw in a dependency, I'd go for fswatch.
@kuon Then feel free to implement it. Good luck!
Just in case, to simply use fswatch you need 25 LoC and erlsh:
@proger fswatch is licensed under GPL 3. That's fine for most hobbyists and some local development, but it's unusable for anything real. watchman has a much better license, platform interop and larger community; 3rd-party bindings (untested).
@steakknife Great find! I was not aware of this tool. Fortunately, it's not a lot of work to add support for watchman ;)
Watchman BSD support is not actively developed. See the note at the top: https://facebook.github.io/watchman/docs/install.html
@steakknife We could add fswatch support without bundling it. And if it's not in the PATH, just print a message.
@kuon If you need BSD watchman support, then feel free to volunteer. :)
what about degrading the message from [error] to [warning] in the meanwhile:
[warning] fs does not support the current operating system: automatic code reloading might not work
or similar?
sorry for the not re- or pre-thought pull request.
https://github.com/duke-m/kqclient
can we try to use this as a base for the fs-bsd-port?
sys/kq.erl sketch:
known_events() -> [renamed, removed, modified, undefined].
start_port(Path, Cwd) ->
Path1 = filename:absname(Path),
Args = [Path1],
erlang:open_port({spawn_executable, find_executable()},
[stream, exit_status, {line, 16384}, {args, Args}, {cd, Cwd}]).
line_to_event(Line) ->
{match, [Path, F]} = re:run(Line, re(), [{capture, all_but_first, list}]),
Flag = [convert_flag(F)],
{Path, Flag}.
convert_flag("WRITE") -> modified;
convert_flag("DELETE") -> removed;
convert_flag("RENAME") -> renamed;
convert_flag(_) -> undefined.
re() ->
case get(kq_re) of
undefined ->
{ok, R} = re:compile("^(.*) ([A-Z]+) .* .*$", [unicode]),
put(kq_re, R),
R;
V -> V
end.