lib/flay.rb in flay-2.5.0 vs lib/flay.rb in flay-2.6.0
- old
+ new
@@ -1,23 +1,23 @@
#!/usr/bin/env ruby -w
-require 'optparse'
-require 'rubygems'
-require 'sexp_processor'
-require 'ruby_parser'
-require 'timeout'
+require "optparse"
+require "rubygems"
+require "sexp_processor"
+require "ruby_parser"
+require "timeout"
class File
RUBY19 = "<3".respond_to? :encoding unless defined? RUBY19 # :nodoc:
class << self
alias :binread :read unless RUBY19
end
end
class Flay
- VERSION = "2.5.0" # :nodoc:
+ VERSION = "2.6.0" # :nodoc:
class Item < Struct.new(:structural_hash, :name, :bonus, :mass, :locations)
alias identical? bonus
end
@@ -47,65 +47,65 @@
def self.parse_options args = ARGV
options = self.default_options
OptionParser.new do |opts|
- opts.banner = 'flay [options] files_or_dirs'
+ opts.banner = "flay [options] files_or_dirs"
opts.version = Flay::VERSION
opts.separator ""
opts.separator "Specific options:"
opts.separator ""
- opts.on('-h', '--help', 'Display this help.') do
+ opts.on("-h", "--help", "Display this help.") do
puts opts
exit
end
- opts.on('-f', '--fuzzy [DIFF]', Integer,
+ opts.on("-f", "--fuzzy [DIFF]", Integer,
"Detect fuzzy (copy & paste) duplication (default 1).") do |n|
options[:fuzzy] = n || 1
end
- opts.on('-l', '--liberal', "Use a more liberal detection method.") do
+ opts.on("-l", "--liberal", "Use a more liberal detection method.") do
options[:liberal] = true
end
- opts.on('-m', '--mass MASS', Integer,
+ opts.on("-m", "--mass MASS", Integer,
"Sets mass threshold (default = #{options[:mass]})") do |m|
options[:mass] = m.to_i
end
- opts.on('-#', "Don't number output (helps with diffs)") do |m|
+ opts.on("-#", "Don't number output (helps with diffs)") do |m|
options[:number] = false
end
- opts.on('-v', '--verbose', "Verbose. Show progress processing files.") do
+ opts.on("-v", "--verbose", "Verbose. Show progress processing files.") do
options[:verbose] = true
end
- opts.on('-o', '--only NODE', String, "Only show matches on NODE type.") do |s|
+ opts.on("-o", "--only NODE", String, "Only show matches on NODE type.") do |s|
options[:only] = s.to_sym
end
- opts.on('-d', '--diff', "Diff Mode. Display N-Way diff for ruby.") do
+ opts.on("-d", "--diff", "Diff Mode. Display N-Way diff for ruby.") do
options[:diff] = true
end
- opts.on('-s', '--summary', "Summarize. Show flay score per file only.") do
+ opts.on("-s", "--summary", "Summarize. Show flay score per file only.") do
options[:summary] = true
end
- opts.on('-t', '--timeout TIME', Integer,
+ opts.on("-t", "--timeout TIME", Integer,
"Set the timeout. (default = #{options[:timeout]})") do |t|
options[:timeout] = t.to_i
end
- extensions = ['rb'] + Flay.load_plugins
+ extensions = ["rb"] + Flay.load_plugins
opts.separator ""
- opts.separator "Known extensions: #{extensions.join(', ')}"
+ opts.separator "Known extensions: #{extensions.join(", ")}"
extensions.each do |meth|
msg = "options_#{meth}"
send msg, opts, options if self.respond_to?(msg)
end
@@ -124,32 +124,68 @@
# Expands +*dirs+ to all files within that match ruby and rake extensions.
# --
# REFACTOR: from flog
def self.expand_dirs_to_files *dirs
- extensions = ['rb'] + Flay.load_plugins
+ extensions = ["rb"] + Flay.load_plugins
dirs.flatten.map { |p|
if File.directory? p then
- Dir[File.join(p, '**', "*.{#{extensions.join(',')}}")]
+ Dir[File.join(p, "**", "*.{#{extensions.join(",")}}")]
else
p
end
- }.flatten
+ }.flatten.map { |s| s[/^(\.\/)?/] = ""; s } # strip "./" from paths
end
+ # so I can move this to flog wholesale
+ DEFAULT_IGNORE = ".flayignore" # :nodoc:
+
##
+ # A file filter mechanism similar to, but not as extensive as,
+ # .gitignore files:
+ #
+ # + If a pattern does not contain a slash, it is treated as a shell glob.
+ # + If a pattern ends in a slash, it matches on directories (and contents).
+ # + Otherwise, it matches on relative paths.
+ #
+ # File.fnmatch is used throughout, so glob patterns work for all 3 types.
+
+ def self.filter_files files, ignore = DEFAULT_IGNORE
+ ignore_paths = if ignore.respond_to? :read then
+ ignore.read
+ elsif File.exists? ignore then
+ File.read ignore
+ end
+
+ if ignore_paths then
+ nonglobs, globs = ignore_paths.split("\n").partition { |p| p.include? "/" }
+ dirs, ifiles = nonglobs.partition { |p| p.end_with? "/" }
+ dirs = dirs.map { |s| s.chomp "/" }
+
+ only_paths = File::FNM_PATHNAME
+ files = files.reject { |f|
+ dirs.any? { |i| File.fnmatch?(i, File.dirname(f), only_paths) } ||
+ globs.any? { |i| File.fnmatch?(i, f) } ||
+ ifiles.any? { |i| File.fnmatch?(i, f, only_paths) }
+ }
+ end
+
+ files
+ end
+
+ ##
# Loads all flay plugins. Files must be named "flog_*.rb".
def self.load_plugins
unless defined? @@plugins then
@@plugins = []
plugins = Gem.find_files("flay_*.rb").reject { |p| p =~ /flay_task/ }
plugins.each do |plugin|
- plugin_name = File.basename(plugin, '.rb').sub(/^flay_/, '')
+ plugin_name = File.basename(plugin, ".rb").sub(/^flay_/, "")
next if @@plugins.include? plugin_name
begin
load plugin
@@plugins << plugin_name
rescue LoadError => e
@@ -185,11 +221,11 @@
def process(*files) # TODO: rename from process - should act as SexpProcessor
files.each do |file|
warn "Processing #{file}" if option[:verbose]
- ext = File.extname(file).sub(/^\./, '')
+ ext = File.extname(file).sub(/^\./, "")
ext = "rb" if ext.nil? || ext.empty?
msg = "process_#{ext}"
unless respond_to? msg then
warn " Unknown file type: #{ext}, defaulting to ruby"
@@ -316,11 +352,11 @@
new_node = tmpl + subcode
next unless new_node.any? { |sub| Sexp === sub }
next if new_node.mass < self.mass_threshold
- # they're already structurally similar, don't bother adding another
+ # they're already structurally similar, don"t bother adding another
next if self.hashes[new_node.structural_hash].any? { |sub|
sub.file == new_node.file and sub.line == new_node.line
}
self.hashes[new_node.structural_hash] << new_node
@@ -501,23 +537,23 @@
io.puts
nodes = hashes[item.structural_hash]
sources = nodes.map do |s|
- msg = "sexp_to_#{File.extname(s.file).sub(/./, '')}"
+ msg = "sexp_to_#{File.extname(s.file).sub(/./, "")}"
self.respond_to?(msg) ? self.send(msg, s) : sexp_to_rb(s)
end
io.puts n_way_diff(*sources)
end
end
end
def sexp_to_rb sexp
begin
- require 'ruby2ruby'
+ require "ruby2ruby"
rescue LoadError
- return 'ruby2ruby is required for diff'
+ return "ruby2ruby is required for diff"
end
@r2r ||= Ruby2Ruby.new
@r2r.process sexp.deep_clone
end
end