lib/respec/app.rb in respec-0.8.3 vs lib/respec/app.rb in respec-0.9.0

- old
+ new

@@ -10,15 +10,21 @@ @args = args @raw_args = [] end @failures_path = self.class.default_failures_path @update_failures = true + @error = nil process_args end attr_accessor :failures_path + def error + command + @error + end + def command @command ||= program_args + generated_args + raw_args + formatter_args end def program_args @@ -56,10 +62,11 @@ | |Run rspec, recording failed examples for easy rerunning later. | |RESPEC-ARGS may consist of: | + | d Run all spec files changed since the last git commit | f Rerun all failed examples | <N> Rerun only the N-th failure | <file name> Run all specs in this file | <file name:N> Run specs at line N in this file | <other> Run only examples matching this pattern @@ -77,10 +84,11 @@ def process_args args = [] files = [] pass_next_arg = false using_filters = false + changed_only = false @args.each do |arg| if pass_next_arg args << arg pass_next_arg = false elsif rspec_option_that_requires_an_argument?(arg) @@ -92,10 +100,12 @@ @help_only = true elsif arg =~ /\A-/ args << arg elsif arg =~ /\AFAILURES=(.*)\z/ self.failures_path = $1 + elsif arg == 'd' + changed_only = true elsif arg == 'f' # failures_path could still be overridden -- delay evaluation of this. args << lambda do if File.exist?(failures_path) if failures.empty? @@ -115,11 +125,11 @@ if (failure = failures[i - 1]) args << '-e' << failure @update_failures = false using_filters = true else - warn "invalid failure: #{i} for (1..#{failures.size})" + @error = "invalid failure: #{i} for (1..#{failures.size})" end else args << '-e' << arg.gsub(/[$]/, '\\\\\\0') end end @@ -141,13 +151,26 @@ # Since we append our formatter as a file to run, rspec won't fall back to # using 'spec' by default. Add it explicitly here. files << 'spec' if files.empty? + # Filter files only to those changed if 'd' is present. + if changed_only + files = changed_paths(files) + end + # If we selected individual failures to rerun, don't give the files to # rspec, as those files will be run in their entirety. @generated_args = expanded @generated_args.concat(files) + end + + def changed_paths(paths) + changes = `git status --short --untracked-files=all #{paths.shelljoin}` + changes.lines.map do |line| + path = line[3..-1].chomp + path if File.exist?(path) && path =~ /\.rb\z/i + end.compact.uniq end def failures @failures ||= if File.exist?(failures_path)