flay 2.5.0 → 2.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +2 -1
- data.tar.gz.sig +0 -0
- data/History.txt +7 -0
- data/README.txt +4 -0
- data/Rakefile +2 -0
- data/bin/flay +1 -1
- data/lib/flay.rb +64 -28
- data/lib/flay_erb.rb +3 -3
- data/lib/flay_task.rb +3 -2
- data/lib/gauntlet_flay.rb +8 -8
- data/test/test_flay.rb +48 -5
- metadata +15 -15
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f618784f99890722c0400a5d9bb2724fd2b07758
|
4
|
+
data.tar.gz: 40359e7d4fb354939fb424d03b90ae16f8b2624a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3bc71abbe2ed73ec4ef380e8441587fe601560a88571330500db0bda26e786708abedb8aa376cde0b977a87ab71d71fb7bf839d7d7aac877f4675c3f55f928e8
|
7
|
+
data.tar.gz: 5962022a8e28b9fbd06455663c34dd8973e1d1c87c7ac4e3282dd4edf178b5bdd3f4cf2cfbfd27cadfc4184bc13f8610c6fca5ce904dba89d56213c60ea8cc0c
|
checksums.yaml.gz.sig
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
|
1
|
+
�,v��e���2N�o'L㵵�� �@4!z���ʘ���фu2㤂G��SYC�i��0r��H[F
|
2
|
+
R��IwjH��?��jQ�����Eh�h�H�����رy�k��;V���vP�V?>s3]ˇ+Wm�*8N��Ql2���v�6X �H������<Y�==t�M���<,�(3JM��]Ah�TVp͖X�_���?�?_�o0�o~����8��B�N�t��~\�U|�����/Ys�ѯ�~A�z���F�����
|
data.tar.gz.sig
CHANGED
Binary file
|
data/History.txt
CHANGED
data/README.txt
CHANGED
@@ -25,6 +25,7 @@ braces vs do/end, etc are all ignored. Making this totally rad.
|
|
25
25
|
* Ships with .rb and .erb.
|
26
26
|
* javascript and others will be available separately.
|
27
27
|
* Includes FlayTask for Rakefiles.
|
28
|
+
* Skips files matched via patterns in .flayignore (subset format of .gitignore).
|
28
29
|
* Totally rad.
|
29
30
|
|
30
31
|
== KNOWN EXTENSIONS:
|
@@ -38,6 +39,9 @@ braces vs do/end, etc are all ignored. Making this totally rad.
|
|
38
39
|
|
39
40
|
* Editor integration (emacs, textmate, other contributions welcome).
|
40
41
|
|
42
|
+
* Vim integration started (https://github.com/prophittcorey/vim-flay)
|
43
|
+
- Flays the current file on save, load, or on command
|
44
|
+
|
41
45
|
== SYNOPSIS:
|
42
46
|
|
43
47
|
% flay -v --diff ~/Work/svn/ruby/ruby_1_8/lib/cgi.rb
|
data/Rakefile
CHANGED
@@ -28,11 +28,13 @@ task :debug do
|
|
28
28
|
mass = ENV["M"]
|
29
29
|
diff = ENV["D"]
|
30
30
|
libr = ENV["L"]
|
31
|
+
ver = ENV["V"]
|
31
32
|
|
32
33
|
opts = Flay.parse_options
|
33
34
|
opts[:mass] = mass.to_i if mass
|
34
35
|
opts[:diff] = diff.to_i if diff
|
35
36
|
opts[:liberal] = true if libr
|
37
|
+
opts[:verbose] = true if ver
|
36
38
|
|
37
39
|
flay = Flay.new opts
|
38
40
|
flay.process(*Flay.expand_dirs_to_files(file))
|
data/bin/flay
CHANGED
data/lib/flay.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
#!/usr/bin/env ruby -w
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
3
|
+
require "optparse"
|
4
|
+
require "rubygems"
|
5
|
+
require "sexp_processor"
|
6
|
+
require "ruby_parser"
|
7
|
+
require "timeout"
|
8
8
|
|
9
9
|
class File
|
10
10
|
RUBY19 = "<3".respond_to? :encoding unless defined? RUBY19 # :nodoc:
|
@@ -15,7 +15,7 @@ class File
|
|
15
15
|
end
|
16
16
|
|
17
17
|
class Flay
|
18
|
-
VERSION = "2.
|
18
|
+
VERSION = "2.6.0" # :nodoc:
|
19
19
|
|
20
20
|
class Item < Struct.new(:structural_hash, :name, :bonus, :mass, :locations)
|
21
21
|
alias identical? bonus
|
@@ -49,61 +49,61 @@ class Flay
|
|
49
49
|
options = self.default_options
|
50
50
|
|
51
51
|
OptionParser.new do |opts|
|
52
|
-
opts.banner =
|
52
|
+
opts.banner = "flay [options] files_or_dirs"
|
53
53
|
opts.version = Flay::VERSION
|
54
54
|
|
55
55
|
opts.separator ""
|
56
56
|
opts.separator "Specific options:"
|
57
57
|
opts.separator ""
|
58
58
|
|
59
|
-
opts.on(
|
59
|
+
opts.on("-h", "--help", "Display this help.") do
|
60
60
|
puts opts
|
61
61
|
exit
|
62
62
|
end
|
63
63
|
|
64
|
-
opts.on(
|
64
|
+
opts.on("-f", "--fuzzy [DIFF]", Integer,
|
65
65
|
"Detect fuzzy (copy & paste) duplication (default 1).") do |n|
|
66
66
|
options[:fuzzy] = n || 1
|
67
67
|
end
|
68
68
|
|
69
|
-
opts.on(
|
69
|
+
opts.on("-l", "--liberal", "Use a more liberal detection method.") do
|
70
70
|
options[:liberal] = true
|
71
71
|
end
|
72
72
|
|
73
|
-
opts.on(
|
73
|
+
opts.on("-m", "--mass MASS", Integer,
|
74
74
|
"Sets mass threshold (default = #{options[:mass]})") do |m|
|
75
75
|
options[:mass] = m.to_i
|
76
76
|
end
|
77
77
|
|
78
|
-
opts.on(
|
78
|
+
opts.on("-#", "Don't number output (helps with diffs)") do |m|
|
79
79
|
options[:number] = false
|
80
80
|
end
|
81
81
|
|
82
|
-
opts.on(
|
82
|
+
opts.on("-v", "--verbose", "Verbose. Show progress processing files.") do
|
83
83
|
options[:verbose] = true
|
84
84
|
end
|
85
85
|
|
86
|
-
opts.on(
|
86
|
+
opts.on("-o", "--only NODE", String, "Only show matches on NODE type.") do |s|
|
87
87
|
options[:only] = s.to_sym
|
88
88
|
end
|
89
89
|
|
90
|
-
opts.on(
|
90
|
+
opts.on("-d", "--diff", "Diff Mode. Display N-Way diff for ruby.") do
|
91
91
|
options[:diff] = true
|
92
92
|
end
|
93
93
|
|
94
|
-
opts.on(
|
94
|
+
opts.on("-s", "--summary", "Summarize. Show flay score per file only.") do
|
95
95
|
options[:summary] = true
|
96
96
|
end
|
97
97
|
|
98
|
-
opts.on(
|
98
|
+
opts.on("-t", "--timeout TIME", Integer,
|
99
99
|
"Set the timeout. (default = #{options[:timeout]})") do |t|
|
100
100
|
options[:timeout] = t.to_i
|
101
101
|
end
|
102
102
|
|
103
|
-
extensions = [
|
103
|
+
extensions = ["rb"] + Flay.load_plugins
|
104
104
|
|
105
105
|
opts.separator ""
|
106
|
-
opts.separator "Known extensions: #{extensions.join(
|
106
|
+
opts.separator "Known extensions: #{extensions.join(", ")}"
|
107
107
|
|
108
108
|
extensions.each do |meth|
|
109
109
|
msg = "options_#{meth}"
|
@@ -126,15 +126,51 @@ class Flay
|
|
126
126
|
# REFACTOR: from flog
|
127
127
|
|
128
128
|
def self.expand_dirs_to_files *dirs
|
129
|
-
extensions = [
|
129
|
+
extensions = ["rb"] + Flay.load_plugins
|
130
130
|
|
131
131
|
dirs.flatten.map { |p|
|
132
132
|
if File.directory? p then
|
133
|
-
Dir[File.join(p,
|
133
|
+
Dir[File.join(p, "**", "*.{#{extensions.join(",")}}")]
|
134
134
|
else
|
135
135
|
p
|
136
136
|
end
|
137
|
-
}.flatten
|
137
|
+
}.flatten.map { |s| s[/^(\.\/)?/] = ""; s } # strip "./" from paths
|
138
|
+
end
|
139
|
+
|
140
|
+
# so I can move this to flog wholesale
|
141
|
+
DEFAULT_IGNORE = ".flayignore" # :nodoc:
|
142
|
+
|
143
|
+
##
|
144
|
+
# A file filter mechanism similar to, but not as extensive as,
|
145
|
+
# .gitignore files:
|
146
|
+
#
|
147
|
+
# + If a pattern does not contain a slash, it is treated as a shell glob.
|
148
|
+
# + If a pattern ends in a slash, it matches on directories (and contents).
|
149
|
+
# + Otherwise, it matches on relative paths.
|
150
|
+
#
|
151
|
+
# File.fnmatch is used throughout, so glob patterns work for all 3 types.
|
152
|
+
|
153
|
+
def self.filter_files files, ignore = DEFAULT_IGNORE
|
154
|
+
ignore_paths = if ignore.respond_to? :read then
|
155
|
+
ignore.read
|
156
|
+
elsif File.exists? ignore then
|
157
|
+
File.read ignore
|
158
|
+
end
|
159
|
+
|
160
|
+
if ignore_paths then
|
161
|
+
nonglobs, globs = ignore_paths.split("\n").partition { |p| p.include? "/" }
|
162
|
+
dirs, ifiles = nonglobs.partition { |p| p.end_with? "/" }
|
163
|
+
dirs = dirs.map { |s| s.chomp "/" }
|
164
|
+
|
165
|
+
only_paths = File::FNM_PATHNAME
|
166
|
+
files = files.reject { |f|
|
167
|
+
dirs.any? { |i| File.fnmatch?(i, File.dirname(f), only_paths) } ||
|
168
|
+
globs.any? { |i| File.fnmatch?(i, f) } ||
|
169
|
+
ifiles.any? { |i| File.fnmatch?(i, f, only_paths) }
|
170
|
+
}
|
171
|
+
end
|
172
|
+
|
173
|
+
files
|
138
174
|
end
|
139
175
|
|
140
176
|
##
|
@@ -147,7 +183,7 @@ class Flay
|
|
147
183
|
plugins = Gem.find_files("flay_*.rb").reject { |p| p =~ /flay_task/ }
|
148
184
|
|
149
185
|
plugins.each do |plugin|
|
150
|
-
plugin_name = File.basename(plugin,
|
186
|
+
plugin_name = File.basename(plugin, ".rb").sub(/^flay_/, "")
|
151
187
|
next if @@plugins.include? plugin_name
|
152
188
|
begin
|
153
189
|
load plugin
|
@@ -187,7 +223,7 @@ class Flay
|
|
187
223
|
files.each do |file|
|
188
224
|
warn "Processing #{file}" if option[:verbose]
|
189
225
|
|
190
|
-
ext = File.extname(file).sub(/^\./,
|
226
|
+
ext = File.extname(file).sub(/^\./, "")
|
191
227
|
ext = "rb" if ext.nil? || ext.empty?
|
192
228
|
msg = "process_#{ext}"
|
193
229
|
|
@@ -318,7 +354,7 @@ class Flay
|
|
318
354
|
next unless new_node.any? { |sub| Sexp === sub }
|
319
355
|
next if new_node.mass < self.mass_threshold
|
320
356
|
|
321
|
-
# they're already structurally similar, don
|
357
|
+
# they're already structurally similar, don"t bother adding another
|
322
358
|
next if self.hashes[new_node.structural_hash].any? { |sub|
|
323
359
|
sub.file == new_node.file and sub.line == new_node.line
|
324
360
|
}
|
@@ -503,7 +539,7 @@ class Flay
|
|
503
539
|
nodes = hashes[item.structural_hash]
|
504
540
|
|
505
541
|
sources = nodes.map do |s|
|
506
|
-
msg = "sexp_to_#{File.extname(s.file).sub(/./,
|
542
|
+
msg = "sexp_to_#{File.extname(s.file).sub(/./, "")}"
|
507
543
|
self.respond_to?(msg) ? self.send(msg, s) : sexp_to_rb(s)
|
508
544
|
end
|
509
545
|
|
@@ -514,9 +550,9 @@ class Flay
|
|
514
550
|
|
515
551
|
def sexp_to_rb sexp
|
516
552
|
begin
|
517
|
-
require
|
553
|
+
require "ruby2ruby"
|
518
554
|
rescue LoadError
|
519
|
-
return
|
555
|
+
return "ruby2ruby is required for diff"
|
520
556
|
end
|
521
557
|
@r2r ||= Ruby2Ruby.new
|
522
558
|
@r2r.process sexp.deep_clone
|
data/lib/flay_erb.rb
CHANGED
data/lib/flay_task.rb
CHANGED
@@ -40,11 +40,12 @@ class FlayTask < Rake::TaskLib
|
|
40
40
|
# Defines the flay task.
|
41
41
|
|
42
42
|
def define
|
43
|
-
desc "Analyze for code duplication in: #{dirs.join(
|
43
|
+
desc "Analyze for code duplication in: #{dirs.join(", ")}"
|
44
44
|
task name do
|
45
45
|
require "flay"
|
46
46
|
flay = Flay.new
|
47
|
-
|
47
|
+
files = Flay.filter_files Flay.expand_dirs_to_files dirs
|
48
|
+
flay.process(*files)
|
48
49
|
flay.report if verbose
|
49
50
|
|
50
51
|
raise "Flay total too high! #{flay.total} > #{threshold}" if
|
data/lib/gauntlet_flay.rb
CHANGED
@@ -1,24 +1,24 @@
|
|
1
1
|
#!/usr/bin/ruby -ws
|
2
2
|
|
3
|
-
$: <<
|
3
|
+
$: << "lib" << "../../ParseTree/dev/lib" << "../../flay/dev/lib"
|
4
4
|
|
5
5
|
$v ||= false # HACK
|
6
6
|
|
7
|
-
require
|
8
|
-
require
|
7
|
+
require "rubygems"
|
8
|
+
require "flay"
|
9
9
|
|
10
|
-
require
|
11
|
-
require
|
10
|
+
require "gauntlet"
|
11
|
+
require "pp"
|
12
12
|
|
13
13
|
# :stopdoc:
|
14
14
|
class FlayGauntlet < Gauntlet
|
15
15
|
$owners = {}
|
16
|
-
$score_file =
|
16
|
+
$score_file = "flay-scores.yml"
|
17
17
|
$misc_error = {:total => -1, :average => -1, :methods => {}}
|
18
18
|
$syntax_error = {:total => -2, :average => -2, :methods => {}}
|
19
19
|
$no_gem = {:total => -4, :average => -4, :methods => {}}
|
20
20
|
|
21
|
-
# copied straight from hoedown.rb
|
21
|
+
# copied straight from hoedown.rb
|
22
22
|
my_projects = %w[InlineFortran ParseTree RubyInline RubyToC
|
23
23
|
ZenHacks ZenTest bfts box_layout
|
24
24
|
change_class flay flog gauntlet heckle
|
@@ -31,7 +31,7 @@ class FlayGauntlet < Gauntlet
|
|
31
31
|
|
32
32
|
def run name
|
33
33
|
warn name
|
34
|
-
self.data[name] = score_for
|
34
|
+
self.data[name] = score_for "."
|
35
35
|
self.dirty = true
|
36
36
|
end
|
37
37
|
|
data/test/test_flay.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
#!/usr/bin/ruby -w
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "minitest/autorun"
|
4
|
+
require "flay"
|
5
|
+
require "tmpdir"
|
5
6
|
|
6
7
|
$: << "../../sexp_processor/dev/lib"
|
7
8
|
|
@@ -225,7 +226,7 @@ class TestSexp < Minitest::Test
|
|
225
226
|
(string):6
|
226
227
|
END
|
227
228
|
|
228
|
-
assert_equal
|
229
|
+
assert_equal "", err
|
229
230
|
assert_equal exp, out.gsub(/\d+/, "N")
|
230
231
|
end
|
231
232
|
|
@@ -281,7 +282,7 @@ class TestSexp < Minitest::Test
|
|
281
282
|
end
|
282
283
|
END
|
283
284
|
|
284
|
-
assert_equal
|
285
|
+
assert_equal "", err
|
285
286
|
assert_equal exp, out.gsub(/\d+/, "N").gsub(/^ {3}$/, "")
|
286
287
|
end
|
287
288
|
|
@@ -311,7 +312,7 @@ class TestSexp < Minitest::Test
|
|
311
312
|
B: source code 6
|
312
313
|
END
|
313
314
|
|
314
|
-
assert_equal
|
315
|
+
assert_equal "", err
|
315
316
|
assert_equal exp, out.gsub(/\d+/, "N").gsub(/^ {3}$/, "")
|
316
317
|
end
|
317
318
|
|
@@ -435,4 +436,46 @@ class TestSexp < Minitest::Test
|
|
435
436
|
|
436
437
|
assert_equal exp, flay.n_way_diff(*dog_and_cat).gsub(/^ {3}$/, "")
|
437
438
|
end
|
439
|
+
|
440
|
+
def test_cls_expand_dirs_to_files
|
441
|
+
Dir.mktmpdir do |dir|
|
442
|
+
Dir.chdir dir do
|
443
|
+
FileUtils.touch "dog_and_cat.rb"
|
444
|
+
|
445
|
+
files = Flay.expand_dirs_to_files "."
|
446
|
+
assert_equal %w[dog_and_cat.rb], files
|
447
|
+
end
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
def assert_filter_files exp, filter, files = %w[test/dog_and_cat.rb]
|
452
|
+
ignore = StringIO.new filter
|
453
|
+
act = Flay.filter_files files, ignore
|
454
|
+
assert_equal exp, act
|
455
|
+
end
|
456
|
+
|
457
|
+
def test_cls_filter_files_dir
|
458
|
+
assert_filter_files [], "test/"
|
459
|
+
end
|
460
|
+
|
461
|
+
def test_cls_filter_files_files
|
462
|
+
assert_filter_files [], "test/*.rb"
|
463
|
+
|
464
|
+
example = %w[test/file.rb test/sub/file.rb top/test/perf.rb]
|
465
|
+
|
466
|
+
assert_filter_files example[1..-1], "test/*.rb", example
|
467
|
+
end
|
468
|
+
|
469
|
+
def test_cls_filter_files_glob
|
470
|
+
assert_filter_files [], "test*"
|
471
|
+
assert_filter_files [], "test*", ["test/lib/woot.rb"]
|
472
|
+
assert_filter_files [], "*.rb"
|
473
|
+
assert_filter_files [], "*dog*.rb"
|
474
|
+
end
|
475
|
+
|
476
|
+
def test_cls_filter_files_glob_miss
|
477
|
+
miss = %w[test/dog_and_cat.rb]
|
478
|
+
assert_filter_files miss, "test"
|
479
|
+
assert_filter_files miss, "nope"
|
480
|
+
end
|
438
481
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flay
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Davis
|
@@ -10,9 +10,9 @@ bindir: bin
|
|
10
10
|
cert_chain:
|
11
11
|
- |
|
12
12
|
-----BEGIN CERTIFICATE-----
|
13
|
-
|
13
|
+
MIIDPjCCAiagAwIBAgIBAjANBgkqhkiG9w0BAQUFADBFMRMwEQYDVQQDDApyeWFu
|
14
14
|
ZC1ydWJ5MRkwFwYKCZImiZPyLGQBGRYJemVuc3BpZGVyMRMwEQYKCZImiZPyLGQB
|
15
|
-
|
15
|
+
GRYDY29tMB4XDTE0MDkxNzIzMDcwN1oXDTE1MDkxNzIzMDcwN1owRTETMBEGA1UE
|
16
16
|
AwwKcnlhbmQtcnVieTEZMBcGCgmSJomT8ixkARkWCXplbnNwaWRlcjETMBEGCgmS
|
17
17
|
JomT8ixkARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALda
|
18
18
|
b9DCgK+627gPJkB6XfjZ1itoOQvpqH1EXScSaba9/S2VF22VYQbXU1xQXL/WzCkx
|
@@ -22,14 +22,14 @@ cert_chain:
|
|
22
22
|
qhtV7HJxNKuPj/JFH0D2cswvzznE/a5FOYO68g+YCuFi5L8wZuuM8zzdwjrWHqSV
|
23
23
|
gBEfoTEGr7Zii72cx+sCAwEAAaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAw
|
24
24
|
HQYDVR0OBBYEFEfFe9md/r/tj/Wmwpy+MI8d9k/hMA0GCSqGSIb3DQEBBQUAA4IB
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
AQAFoDJRokCQdxFfOrmsKX41KOFlU/zjrbDVM9hgB/Ur999M6OXGSi8FitXNtMwY
|
26
|
+
FVjsiAPeU7HaWVVcZkj6IhINelTkXsxgGz/qCzjHy3iUMuZWw36cS0fiWJ5rvH+e
|
27
|
+
hD7uXxJSFuyf1riDGI1aeWbQ74WMwvNstOxLUMiV5a1fzBhlxPqb537ubDjq/M/h
|
28
|
+
zPUFPVYeL5KjDHLCqI2FwIk2sEMOQgjpXHzl+3NlD2LUgUhHDMevmgVua0e2GT1B
|
29
|
+
xJcC6UN6NHMOVMyAXsr2HR0gRRx4ofN1LoP2KhXzSr8UMvQYlwPmE0N5GQv1b5AO
|
30
|
+
VpzF30vNaJK6ZT7xlIsIlwmH
|
31
31
|
-----END CERTIFICATE-----
|
32
|
-
date:
|
32
|
+
date: 2015-01-10 00:00:00.000000000 Z
|
33
33
|
dependencies:
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
35
|
name: sexp_processor
|
@@ -65,14 +65,14 @@ dependencies:
|
|
65
65
|
requirements:
|
66
66
|
- - ~>
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '5.
|
68
|
+
version: '5.5'
|
69
69
|
type: :development
|
70
70
|
prerelease: false
|
71
71
|
version_requirements: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ~>
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '5.
|
75
|
+
version: '5.5'
|
76
76
|
- !ruby/object:Gem::Dependency
|
77
77
|
name: rdoc
|
78
78
|
requirement: !ruby/object:Gem::Requirement
|
@@ -93,14 +93,14 @@ dependencies:
|
|
93
93
|
requirements:
|
94
94
|
- - ~>
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '3.
|
96
|
+
version: '3.13'
|
97
97
|
type: :development
|
98
98
|
prerelease: false
|
99
99
|
version_requirements: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - ~>
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '3.
|
103
|
+
version: '3.13'
|
104
104
|
description: |-
|
105
105
|
Flay analyzes code for structural similarities. Differences in literal
|
106
106
|
values, variable, class, method names, whitespace, programming style,
|
@@ -148,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
148
|
version: '0'
|
149
149
|
requirements: []
|
150
150
|
rubyforge_project:
|
151
|
-
rubygems_version: 2.
|
151
|
+
rubygems_version: 2.4.1
|
152
152
|
signing_key:
|
153
153
|
specification_version: 4
|
154
154
|
summary: Flay analyzes code for structural similarities
|
metadata.gz.sig
CHANGED
Binary file
|