Skip to content

Commit

Permalink
Merge pull request #28 from guard/detect_unwatched_gemfile
Browse files Browse the repository at this point in the history
Detect unwatched gemfile
  • Loading branch information
e2 committed Dec 11, 2014
2 parents 4ecf4a7 + d791e6d commit 314a2f5
Show file tree
Hide file tree
Showing 8 changed files with 233 additions and 12 deletions.
1 change: 1 addition & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
--color
--require spec_helper
--format doc
7 changes: 3 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ rvm:
matrix:
allow_failures:
- rvm: rbx

notifications:
recipients:
- remy@rymai.me
branches:
only:
- master
17 changes: 13 additions & 4 deletions Guardfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,17 @@ guard :bundler do
watch(%r{^.+\.gemspec$})
end

guard :rspec do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
watch('spec/spec_helper.rb') { 'spec' }
guard :rspec, cmd: "bundle exec rspec" do
require "ostruct"

rspec = OpenStruct.new
rspec.spec_dir = "spec"
rspec.spec = ->(m) { "#{rspec.spec_dir}/#{m}_spec.rb" }
rspec.spec_helper = "#{rspec.spec_dir}/spec_helper.rb"
rspec.spec_files = %r{^#{rspec.spec_dir}/.+_spec\.rb$}
rspec.lib_files = %r{^lib/(.+)\.rb$}

watch(rspec.spec_files)
watch(rspec.lib_files) { |m| rspec.spec.(m[1]) }
watch(rspec.spec_helper) { rspec.spec_dir }
end
2 changes: 1 addition & 1 deletion guard-bundler.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Gem::Specification.new do |s|
s.required_ruby_version = '>= 1.9.2'

s.add_dependency 'guard', '~> 2.2'
s.add_dependency 'guard-compat', '~> 1.0'
s.add_dependency 'guard-compat', '~> 1.1'
s.add_dependency 'bundler', '~> 1.0'

s.files = Dir.glob('{lib}/**/*') + %w[LICENSE README.md]
Expand Down
12 changes: 9 additions & 3 deletions lib/guard/bundler/templates/Guardfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
guard :bundler do
watch('Gemfile')
# Uncomment next line if your Gemfile contains the `gemspec' command.
# watch(/^.+\.gemspec/)
require 'guard/bundler'
require 'guard/bundler/verify'
helper = Guard::Bundler::Verify.new

files = ['Gemfile']
files += Dir['*.gemspec'] if files.any? { |f| helper.uses_gemspec?(f) }

# Assume files are symlinked from somewhere
files.each { |file| watch(helper.real_path(file)) }
end
54 changes: 54 additions & 0 deletions lib/guard/bundler/verify.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
require 'pathname'

module Guard
class Bundler < Plugin
class Verify
if Gem.win_platform?
SYMLINK_NEEDED = <<-EOS
Error: Guard will not detect changes to your Gemfile!
Solution: move the Gemfile to a watched directory and symlink it, so that
'Gemfile' is symlinked e.g. to config/Gemfile.
(See: https://github.com/guard/guard/wiki/Optimizing-for-large-projects)
EOS
else
SYMLINK_NEEDED = <<-EOS
Error: Guard will not detect changes to your Gemfile!
Solution: move the Gemfile to a watched directory and symlink it back.
Example:
$ mkdir config
$ git mv Gemfile config # use just 'mv' if this doesn't work
$ ln -s config/Gemfile .
and add config to the `directories` statement in your Guardfile.
(See: https://github.com/guard/guard/wiki/Optimizing-for-large-projects)
EOS
end

def verify!(file)
watchdirs = Guard::Compat.watched_directories

gemfile = Pathname.new(file)
config_dir = gemfile.realpath.dirname
return if watchdirs.include?(config_dir)

Compat::UI.error SYMLINK_NEEDED
end

def real_path(file)
verify!(file)
Pathname.new(file).realpath.relative_path_from(Pathname.pwd).to_s
end

def uses_gemspec?(file)
IO.read(file).lines.map(&:strip).grep(/^gemspec$/).any?
end
end
end
end
74 changes: 74 additions & 0 deletions spec/guard/bundler/template_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
require "guard/compat/test/template"

require "guard/bundler"

# This is included by the template
require "guard/bundler/verify"

module Guard
RSpec.describe Bundler do
describe "template" do
subject { Compat::Test::Template.new(described_class) }

let(:helper) { instance_double(Bundler::Verify) }

before do
allow(Bundler::Verify).to receive(:new).and_return(helper)
allow(helper).to receive(:uses_gemspec?).and_return(true)

allow(helper).to receive(:real_path).with('Gemfile').
and_return('Gemfile')

allow(Dir).to receive(:[]).and_return(%w(guard-foo.gemspec))

allow(helper).to receive(:real_path).with('guard-foo.gemspec').
and_return('guard-foo.gemspec')
end

context "when gemspec is used" do
before do
allow(helper).to receive(:uses_gemspec?).with('Gemfile').
and_return(true)
end

it "watches the gemspec" do
expect(subject.changed('config/guard-foo.gemspec')).
to eq(%w(config/guard-foo.gemspec))
end
end

context "when gemspec is not used" do
before do
allow(helper).to receive(:uses_gemspec?).with('Gemfile').
and_return(false)
end

it "does not watch the gemspec" do
expect(subject.changed('guard-foo.gemspec')).to eq(%w())
end
end

context "when Gemfile is not a symlink" do
before do
expect(helper).to receive(:real_path).with('Gemfile').
and_return('Gemfile')
end

it "watches Gemfile" do
expect(subject.changed('Gemfile')).to eq(%w(Gemfile))
end
end

context "with a symlinked Gemfile" do
before do
expect(helper).to receive(:real_path).with('Gemfile').
and_return('config/Gemfile')
end

it "watches the real Gemfile" do
expect(subject.changed('config/Gemfile')).to eq(%w(config/Gemfile))
end
end
end
end
end
78 changes: 78 additions & 0 deletions spec/guard/bundler/verify_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
require "guard/bundler/verify"

RSpec.describe Guard::Bundler::Verify do
describe '#uses_gemspec?' do
context "when gemspec is used" do
before do
allow(IO).to receive(:read).with('foo').and_return("\n\n gemspec \n")
end

it "detects used gemspec" do
expect(subject.uses_gemspec?('foo')).to be_truthy
end
end

context "when gemspec is not used" do
before do
allow(IO).to receive(:read).with('foo').and_return("gem 'rspec'\n")
end

it "does not detects gemspec usage" do
expect(subject.uses_gemspec?('foo')).to be_falsey
end
end
end

describe '#real_path' do
context "when Gemfile is not watched" do
before do
allow(Guard::Compat).to receive(:watched_directories).and_return(['/foo'])
end

it 'shows error' do
expect(Guard::Compat::UI).to receive(:error).
with(/Guard will not detect changes/)
subject.real_path('Gemfile')
end
end

context "when Gemfile is watched along with whole project" do
before do
allow(Guard::Compat).to receive(:watched_directories).
and_return([Pathname.pwd])
end

it 'shows no error' do
expect(Guard::Compat::UI).to_not receive(:error)
subject.real_path('Gemfile')
end

it 'returns relative path to file' do
expect(subject.real_path('Gemfile')).to eq('Gemfile')
end
end

context "when subdir is watched" do
before do
allow(Guard::Compat).to receive(:watched_directories).
and_return([Pathname.pwd + 'foo'])
end

context "when Gemfile is symlinked" do
before do
allow_any_instance_of(Pathname).to receive(:realpath).
and_return(Pathname.pwd + 'foo/Gemfile')
end

it "returns the relative real path" do
expect(subject.real_path('Gemfile')).to eq('foo/Gemfile')
end

it 'shows no error' do
expect(Guard::Compat::UI).to_not receive(:error)
subject.real_path('Gemfile')
end
end
end
end
end

0 comments on commit 314a2f5

Please sign in to comment.