-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
module Listen | ||
# @private api | ||
class Record | ||
# Represents a directory entry (dir or file) | ||
class Entry | ||
# file: "/home/me/watched_dir", "app/models", "foo.rb" | ||
# dir, "/home/me/watched_dir", "." | ||
def initialize(root, relative, name = nil) | ||
@root, @relative, @name = root, relative, name | ||
end | ||
|
||
attr_reader :root, :relative, :name | ||
|
||
def children | ||
child_relative = _join | ||
(Dir.entries(sys_path) - %w(. ..)).map do |name| | ||
Entry.new(@root, child_relative, name) | ||
end | ||
end | ||
|
||
def meta | ||
lstat = ::File.lstat(sys_path) | ||
{ mtime: lstat.mtime.to_f, mode: lstat.mode } | ||
end | ||
|
||
# record hash is e.g. | ||
# if @record["/home/me/watched_dir"]["project/app/models"]["foo.rb"] | ||
# if @record["/home/me/watched_dir"]["project/app"]["models"] | ||
# record_dir_key is "project/app/models" | ||
def record_dir_key | ||
::File.join(*[@relative, @name].compact) | ||
end | ||
|
||
def sys_path | ||
# Use full path in case someone uses chdir | ||
::File.join(*[@root, @relative, @name].compact) | ||
end | ||
|
||
def real_path | ||
@real_path ||= ::File.realpath(sys_path) | ||
end | ||
|
||
private | ||
|
||
def _join | ||
args = [@relative, @name].compact | ||
args.empty? ? nil : ::File.join(*args) | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
require 'set' | ||
|
||
module Listen | ||
# @private api | ||
class Record | ||
class SymlinkDetector | ||
SYMLINK_LOOP_ERROR = <<-EOS | ||
** ERROR: Listen detected a duplicate directory being watched! ** | ||
(This may be due to symlinks pointing to parent directories). | ||
Duplicate: %s | ||
which already is added as: %s | ||
Listen is refusing to continue, because this may likely result in | ||
an infinite loop. | ||
Suggestions: | ||
1) (best option) watch only directories you care about, e.g. | ||
either symlinked folders or folders with the real directories, | ||
but not both. | ||
2) reorganize your project so that watched directories do not | ||
contain symlinked directories | ||
3) submit patches so that Listen can reliably and quickly (!) | ||
detect symlinks to already watched read directories, skip | ||
them, and then reasonably choose which symlinked paths to | ||
report as changed (if any) | ||
4) (not worth it) help implement a "reverse symlink lookup" | ||
function in Listen, which - given a real directory - would | ||
return all the symlinks pointing to that directory | ||
Issue: https://github.com/guard/listen/issues/259 | ||
EOS | ||
|
||
def initialize | ||
@real_dirs = Set.new | ||
end | ||
|
||
def verify_unwatched!(entry) | ||
real_path = entry.real_path | ||
@real_dirs.add?(real_path) || _fail(entry.sys_path, real_path) | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
e2
Author
|
||
end | ||
|
||
private | ||
|
||
def _fail(symlinked, real_path) | ||
STDERR.puts format(SYMLINK_LOOP_ERROR, symlinked, real_path) | ||
|
||
# Note Celluloid eats up abort message anyway | ||
fail 'Failed due to looped symlinks' | ||
end | ||
end | ||
end | ||
end |
1 comment
on commit c7b9a75
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm glad to help! :)
This is failure even if the tree of directories are valid ( not looped ) like: