Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

skip already watched symlinked dirs #278

Merged
merged 1 commit into from
Nov 25, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/listen/record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,12 @@ def _fast_build(root)

def _fast_build_dir(remaining, symlink_detector)
entry = remaining.pop
entry.children.each { |child| remaining << child }
symlink_detector.verify_unwatched!(entry)
entry.children.each { |child| remaining << child }
add_dir(entry.root, entry.record_dir_key)
rescue Errno::ENOTDIR
_fast_try_file(entry)
rescue SystemCallError
rescue SystemCallError, SymlinkDetector::Error
_fast_unset_path(entry.root, entry.relative, entry.name)
end

Expand Down
44 changes: 10 additions & 34 deletions lib/listen/record/symlink_detector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,21 @@ 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 multiple symlinks pointing to already watched dirs).

Duplicate: %s

which already is added as: %s

Listen is refusing to continue, because it may cause an infinite loop,
a crash or confusing results.

Suggestions:
WIKI = 'https://github.com/guard/listen/wiki/Duplicate-directory-errors'

1) (best option) watch only directories you care about (e.g.
either symlinked folders or folders with the real directories,
but not both).

IMPORTANT: The `:ignore` options DO NOT HELP here
(see: https://github.com/guard/listen/issues/274)

NOTE: If you are using Listen through some other application
(like Guard, Compass, Jekyll, Vagrant), check the documentation on
selecting watched directories (e.g. Guard has a `-w` option, Compass
allows you to specify multiple input/output directories, etc.)
SYMLINK_LOOP_ERROR = <<-EOS
** ERROR: directory is already being watched! **

2) reorganize your project so that watched directories do not
contain symlinked directories
Directory: %s

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)
is already begin watched through: %s

Issue: https://github.com/guard/listen/issues/259
MORE INFO: #{WIKI}
EOS

class Error < RuntimeError
end

def initialize
@real_dirs = Set.new
end
Expand All @@ -54,9 +32,7 @@ def verify_unwatched!(entry)

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'
fail Error, 'Failed due to looped symlinks'
end
end
end
Expand Down
16 changes: 13 additions & 3 deletions spec/lib/listen/record_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,10 @@

allow(::File).to receive(:realpath).with('/dir1').and_return('/dir1')
allow(::File).to receive(:realpath).with('/dir2').and_return('/dir2')
allow(::File).to receive(:realpath).with('/dir1/foo').
and_return('/dir1/foo')
allow(::File).to receive(:realpath).with('/dir1/bar').
and_return('/dir1/bar')
end

it 'builds record' do
Expand All @@ -256,6 +260,8 @@
allow(::File).to receive(:realpath).with('/dir2').and_return('/dir2')
allow(::File).to receive(:realpath).with('/dir1/foo').
and_return('/dir1/foo')
allow(::File).to receive(:realpath).with('/dir1/foo/bar').
and_return('/dir1/foo/bar')
end

it 'builds record' do
Expand Down Expand Up @@ -295,15 +301,19 @@
before do
allow(::Dir).to receive(:entries).with('/dir1') { %w(foo) }
allow(::Dir).to receive(:entries).with('/dir1/foo') { %w(foo) }
allow(::Dir).to receive(:entries).with('/dir2') { [] }
allow(::File).to receive(:realpath).with('/dir1').and_return('/bar')
allow(::File).to receive(:realpath).with('/dir1/foo').and_return('/bar')
allow(::File).to receive(:realpath).with('/dir2').and_return('/dir2')
end

it 'shows message and aborts with error' do
expect(STDERR).to receive(:puts).with(/detected a duplicate directory/)
expect(STDERR).to receive(:puts).
with(/directory is already being watched/)

expect { record.build }.to raise_error(RuntimeError,
/Failed due to looped symlinks/)
record.build
# expect { record.build }.
# to raise_error(RuntimeError, /Failed due to looped symlinks/)
end
end
end
Expand Down