flog 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +31 -5
- data/Manifest.txt +1 -0
- data/README.txt +5 -5
- data/Rakefile +13 -7
- data/bin/flog +5 -0
- data/gem_updater.rb +161 -0
- data/lib/flog.rb +126 -107
- data/unpack.rb +0 -0
- data/update_scores.rb +89 -82
- metadata +73 -52
data/History.txt
CHANGED
|
@@ -1,10 +1,32 @@
|
|
|
1
|
-
|
|
1
|
+
=== 1.2.0 / 2008-10-22
|
|
2
|
+
|
|
3
|
+
* 14 minor enhancements:
|
|
4
|
+
|
|
5
|
+
* Added -c flag to continue dispite errors.
|
|
6
|
+
* Added -m to only report code in methods (skips #none).
|
|
7
|
+
* Added -n flag to give NO method details (summary only)
|
|
8
|
+
* Added -n to skip method details... pussies should learn grep.
|
|
9
|
+
* Added -q to quiet method details (total per method only)
|
|
10
|
+
* Added avg & stddev to total.
|
|
11
|
+
* Added avg score per method to report.
|
|
12
|
+
* Added lots of doco from contributors (hugh sasse?).
|
|
13
|
+
* Fixed class names when const2/3.
|
|
14
|
+
* Fixed unified ruby changes
|
|
15
|
+
* Refactored flog with help from flay.
|
|
16
|
+
* Refactored get_source_index
|
|
17
|
+
* Refactored into gem_updater.rb and cleaned up.
|
|
18
|
+
* Works with new incremental rubygems, albiet slower than before.
|
|
19
|
+
|
|
20
|
+
=== 1.1.0 / 2007-08-21
|
|
2
21
|
|
|
3
22
|
* 3 major enhancements:
|
|
23
|
+
|
|
4
24
|
* Added assignments and branches and a lot of other stuff. rad.
|
|
5
25
|
* Added process_iter section for DSL style blocks (rake tasks etc).
|
|
6
26
|
* Made Flog usable as a library.
|
|
27
|
+
|
|
7
28
|
* 12 minor enhancements:
|
|
29
|
+
|
|
8
30
|
* Added -a flag to turn off threshold culling for other tools.
|
|
9
31
|
* Added -s for summarizing the score.
|
|
10
32
|
* Added -v feedback to know what file you're flogging.
|
|
@@ -17,23 +39,27 @@
|
|
|
17
39
|
* Added unpack.rb and update_scores.rb at base level (not installed)
|
|
18
40
|
* Added scoring for block_pass.
|
|
19
41
|
* Converted totals to use distance formula on ABC's.
|
|
42
|
+
|
|
20
43
|
* 3 bug fixes:
|
|
44
|
+
|
|
21
45
|
* Ran flog on every latest gem available. Found a bunch of problems.
|
|
22
46
|
* Use a stack for both class/module and method accounting.
|
|
23
47
|
* block_args weren't processing the arg
|
|
24
48
|
|
|
25
|
-
|
|
49
|
+
=== 1.0.2 / 2007-08-01
|
|
26
50
|
|
|
27
51
|
* 1 bug fix:
|
|
52
|
+
|
|
28
53
|
* stupid rubygems bin wrapper... *sigh*
|
|
29
54
|
|
|
30
|
-
|
|
55
|
+
=== 1.0.1 / 2007-08-01
|
|
31
56
|
|
|
32
57
|
* 1 bug fix:
|
|
58
|
+
|
|
33
59
|
* New Rule: NEVER release new software when exhausted: Fixed dependency list.
|
|
34
60
|
|
|
35
|
-
|
|
61
|
+
=== 1.0.0 / 2007-08-01
|
|
36
62
|
|
|
37
63
|
* 1 major enhancement:
|
|
38
|
-
* Birthday!
|
|
39
64
|
|
|
65
|
+
* Birthday!
|
data/Manifest.txt
CHANGED
data/README.txt
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
flog
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
= flog
|
|
2
|
+
|
|
3
|
+
* http://ruby.sadi.st/
|
|
4
|
+
* http://rubyforge.org/projects/seattlerb
|
|
5
5
|
|
|
6
6
|
== DESCRIPTION:
|
|
7
7
|
|
|
@@ -25,7 +25,7 @@ report. The higher the score, the more pain the code is in.
|
|
|
25
25
|
== REQUIREMENTS:
|
|
26
26
|
|
|
27
27
|
* ruby2ruby
|
|
28
|
-
*
|
|
28
|
+
* ParseTree
|
|
29
29
|
|
|
30
30
|
== INSTALL:
|
|
31
31
|
|
data/Rakefile
CHANGED
|
@@ -2,16 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
require 'rubygems'
|
|
4
4
|
require 'hoe'
|
|
5
|
+
|
|
6
|
+
Hoe.add_include_dirs("../../ParseTree/dev/lib",
|
|
7
|
+
"../../RubyInline/dev/lib",
|
|
8
|
+
"../../sexp_processor/dev/lib",
|
|
9
|
+
"../../ZenTest/dev/lib",
|
|
10
|
+
"lib")
|
|
11
|
+
|
|
5
12
|
require './lib/flog'
|
|
6
13
|
|
|
7
|
-
Hoe.new('flog', Flog::VERSION) do |
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[2..-1].map {|u| u.strip }
|
|
12
|
-
p.changes = p.paragraphs_of('History.txt', 1).join("\n\n")
|
|
14
|
+
Hoe.new('flog', Flog::VERSION) do |flog|
|
|
15
|
+
flog.rubyforge_name = 'seattlerb'
|
|
16
|
+
|
|
17
|
+
flog.developer('Ryan Davis', 'ryand-ruby@zenspider.com')
|
|
13
18
|
|
|
14
|
-
|
|
19
|
+
flog.extra_deps << ['sexp_processor', '~> 3.0']
|
|
20
|
+
flog.extra_deps << ["ParseTree", '~> 3.0']
|
|
15
21
|
end
|
|
16
22
|
|
|
17
23
|
# vim: syntax=Ruby
|
data/bin/flog
CHANGED
|
@@ -2,15 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
require 'flog'
|
|
4
4
|
|
|
5
|
+
# In case this is being called on the end of a pipe:
|
|
5
6
|
ARGV.push "-" if ARGV.empty?
|
|
6
7
|
|
|
7
8
|
if defined? $h then
|
|
8
9
|
puts "#{File.basename $0} options dirs_or_files"
|
|
9
10
|
puts " -a display all flog results, not top 60%"
|
|
11
|
+
puts " -c continue despite syntax errors"
|
|
10
12
|
puts " -h display help"
|
|
11
13
|
puts " -I=path extend $LOAD_PATH with path"
|
|
14
|
+
puts " -m skip code outside of methods"
|
|
15
|
+
puts " -n no method details in report"
|
|
12
16
|
puts " -s display total score only"
|
|
13
17
|
puts " -v verbosely display progress and errors"
|
|
18
|
+
puts " -q quiet, don't show method breakdowns"
|
|
14
19
|
exit 0
|
|
15
20
|
end
|
|
16
21
|
|
data/gem_updater.rb
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
require 'rubygems/remote_fetcher'
|
|
2
|
+
|
|
3
|
+
$u ||= false
|
|
4
|
+
|
|
5
|
+
module GemUpdater
|
|
6
|
+
GEMURL = URI.parse 'http://gems.rubyforge.org'
|
|
7
|
+
|
|
8
|
+
@@index = nil
|
|
9
|
+
|
|
10
|
+
def self.stupid_gems
|
|
11
|
+
["ruby-aes-table1-1.0.gem", # stupid dups usually because of "dash" renames
|
|
12
|
+
"ruby-aes-unroll1-1.0.gem",
|
|
13
|
+
"hpricot-scrub-0.2.0.gem",
|
|
14
|
+
"extract_curves-0.0.1.gem",
|
|
15
|
+
"extract_curves-0.0.1-i586-linux.gem",
|
|
16
|
+
"extract_curves-0.0.1-mswin32.gem",
|
|
17
|
+
"rfeedparser-ictv-0.9.931.gem",
|
|
18
|
+
"spec_unit-0.0.1.gem"]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.initialize_dir
|
|
22
|
+
Dir.mkdir "../gems" unless File.directory? "../gems"
|
|
23
|
+
self.in_gem_dir do
|
|
24
|
+
File.symlink ".", "cache" unless File.exist? "cache"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.get_source_index
|
|
29
|
+
return @@index if @@index
|
|
30
|
+
|
|
31
|
+
dump = if $u or not File.exist? '.source_index' then
|
|
32
|
+
url = GEMURL + "Marshal.#{Gem.marshal_version}.Z"
|
|
33
|
+
dump = Gem::RemoteFetcher.fetcher.fetch_path url
|
|
34
|
+
require 'zlib'
|
|
35
|
+
dump = Gem.inflate dump
|
|
36
|
+
open '.source_index', 'wb' do |io| io.write dump end
|
|
37
|
+
dump
|
|
38
|
+
else
|
|
39
|
+
open '.source_index', 'rb' do |io| io.read end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
@@index = Marshal.load dump
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def self.get_latest_gems
|
|
46
|
+
@@cache ||= get_source_index.latest_specs
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.get_gems_by_name
|
|
50
|
+
@@by_name ||= Hash[*get_latest_gems.map { |gem|
|
|
51
|
+
[gem.name, gem, gem.full_name, gem]
|
|
52
|
+
}.flatten]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def self.dependencies_of name
|
|
56
|
+
index = self.get_source_index
|
|
57
|
+
get_gems_by_name[name].dependencies.map { |dep| index.search(dep).last }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def self.dependent_upon name
|
|
61
|
+
get_latest_gems.find_all { |gem|
|
|
62
|
+
gem.dependencies.any? { |dep| dep.name == name }
|
|
63
|
+
}
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def self.update_gem_tarballs
|
|
67
|
+
GemUpdater.initialize_dir
|
|
68
|
+
|
|
69
|
+
latest = GemUpdater.get_latest_gems
|
|
70
|
+
|
|
71
|
+
puts "updating mirror"
|
|
72
|
+
|
|
73
|
+
self.in_gem_dir do
|
|
74
|
+
gems = Dir["*.gem"]
|
|
75
|
+
tgzs = Dir["*.tgz"]
|
|
76
|
+
|
|
77
|
+
old = tgzs - latest.map { |spec| "#{spec.full_name}.tgz" }
|
|
78
|
+
unless old.empty? then
|
|
79
|
+
puts "deleting #{old.size} tgzs"
|
|
80
|
+
old.each do |tgz|
|
|
81
|
+
File.unlink tgz
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
new = latest.map { |spec|
|
|
86
|
+
"#{spec.full_name}.tgz"
|
|
87
|
+
} - tgzs
|
|
88
|
+
|
|
89
|
+
puts "fetching #{new.size} tgzs"
|
|
90
|
+
|
|
91
|
+
latest.sort.each do |spec|
|
|
92
|
+
full_name = spec.full_name
|
|
93
|
+
tgz_name = "#{full_name}.tgz"
|
|
94
|
+
gem_name = "#{full_name}.gem"
|
|
95
|
+
|
|
96
|
+
next if tgzs.include? tgz_name
|
|
97
|
+
|
|
98
|
+
unless gems.include? gem_name then
|
|
99
|
+
begin
|
|
100
|
+
warn "downloading #{full_name}"
|
|
101
|
+
Gem::RemoteFetcher.fetcher.download(spec, GEMURL, Dir.pwd)
|
|
102
|
+
rescue Gem::RemoteFetcher::FetchError
|
|
103
|
+
warn " failed"
|
|
104
|
+
next
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
warn "converting #{gem_name} to tarball"
|
|
109
|
+
|
|
110
|
+
unless File.directory? full_name then
|
|
111
|
+
system "gem unpack cache/#{gem_name}"
|
|
112
|
+
system "gem spec -l cache/#{gem_name} > #{full_name}/gemspec.rb"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
system "tar zmcf #{tgz_name} #{full_name}"
|
|
116
|
+
system "rm -rf #{full_name} #{gem_name}"
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def self.each_gem filter = /^[\w-]+-\d+(\.\d+)*\.tgz$/
|
|
122
|
+
self.in_gem_dir do
|
|
123
|
+
Dir["*.tgz"].each do |tgz|
|
|
124
|
+
next unless tgz =~ filter
|
|
125
|
+
|
|
126
|
+
yield File.basename(tgz, ".tgz")
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def self.with_gem name
|
|
132
|
+
self.in_gem_dir do
|
|
133
|
+
begin
|
|
134
|
+
system "tar zxmf #{name}.tgz 2> /dev/null"
|
|
135
|
+
Dir.chdir name do
|
|
136
|
+
yield name
|
|
137
|
+
end
|
|
138
|
+
ensure
|
|
139
|
+
system "rm -r #{name}"
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def self.load_yaml path, default = {}
|
|
145
|
+
YAML.load(File.read(path)) rescue default
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def self.save_yaml path, data
|
|
149
|
+
File.open("#{path}.new", 'w') do |f|
|
|
150
|
+
warn "*** saving #{path}"
|
|
151
|
+
YAML.dump data, f
|
|
152
|
+
end
|
|
153
|
+
File.rename "#{path}.new", path
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def self.in_gem_dir
|
|
157
|
+
Dir.chdir "../gems" do
|
|
158
|
+
yield
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
data/lib/flog.rb
CHANGED
|
@@ -3,12 +3,16 @@ require 'parse_tree'
|
|
|
3
3
|
require 'sexp_processor'
|
|
4
4
|
require 'unified_ruby'
|
|
5
5
|
|
|
6
|
-
$a ||= false
|
|
7
|
-
$
|
|
8
|
-
$
|
|
6
|
+
$a ||= false # report all methods, not just 60%
|
|
7
|
+
$c ||= false # continue despite syntax errors
|
|
8
|
+
$m ||= false # real methods only (no global scope)
|
|
9
|
+
$n ||= false # no method details
|
|
10
|
+
$s ||= false # summary only
|
|
11
|
+
$v ||= false # verbose, print methods as processed
|
|
12
|
+
$q ||= false # quiet, don't show method details
|
|
9
13
|
|
|
10
14
|
class Flog < SexpProcessor
|
|
11
|
-
VERSION = '1.
|
|
15
|
+
VERSION = '1.2.0'
|
|
12
16
|
|
|
13
17
|
include UnifiedRuby
|
|
14
18
|
|
|
@@ -16,50 +20,58 @@ class Flog < SexpProcessor
|
|
|
16
20
|
SCORES = Hash.new(1)
|
|
17
21
|
BRANCHING = [ :and, :case, :else, :if, :or, :rescue, :until, :when, :while ]
|
|
18
22
|
|
|
23
|
+
##
|
|
19
24
|
# various non-call constructs
|
|
25
|
+
|
|
20
26
|
OTHER_SCORES = {
|
|
21
|
-
:alias
|
|
22
|
-
:assignment
|
|
23
|
-
:block
|
|
24
|
-
:branch
|
|
25
|
-
:lit_fixnum
|
|
26
|
-
:sclass
|
|
27
|
-
:super
|
|
28
|
-
:to_proc_icky!
|
|
27
|
+
:alias => 2,
|
|
28
|
+
:assignment => 1,
|
|
29
|
+
:block => 1,
|
|
30
|
+
:branch => 1,
|
|
31
|
+
:lit_fixnum => 0.25,
|
|
32
|
+
:sclass => 5,
|
|
33
|
+
:super => 1,
|
|
34
|
+
:to_proc_icky! => 10,
|
|
29
35
|
:to_proc_normal => 5,
|
|
30
|
-
:yield
|
|
36
|
+
:yield => 1,
|
|
31
37
|
}
|
|
32
38
|
|
|
39
|
+
##
|
|
33
40
|
# eval forms
|
|
41
|
+
|
|
34
42
|
SCORES.merge!(:define_method => 5,
|
|
35
|
-
:eval
|
|
36
|
-
:module_eval
|
|
37
|
-
:class_eval
|
|
43
|
+
:eval => 5,
|
|
44
|
+
:module_eval => 5,
|
|
45
|
+
:class_eval => 5,
|
|
38
46
|
:instance_eval => 5)
|
|
39
47
|
|
|
48
|
+
##
|
|
40
49
|
# various "magic" usually used for "clever code"
|
|
41
|
-
SCORES.merge!(:alias_method => 2,
|
|
42
|
-
:extend => 2,
|
|
43
|
-
:include => 2,
|
|
44
|
-
:instance_method => 2,
|
|
45
|
-
:instance_methods => 2,
|
|
46
|
-
:method_added => 2,
|
|
47
|
-
:method_defined? => 2,
|
|
48
|
-
:method_removed => 2,
|
|
49
|
-
:method_undefined => 2,
|
|
50
|
-
:private_class_method => 2,
|
|
51
|
-
:private_instance_methods => 2,
|
|
52
|
-
:private_method_defined? => 2,
|
|
53
|
-
:protected_instance_methods => 2,
|
|
54
|
-
:protected_method_defined? => 2,
|
|
55
|
-
:public_class_method => 2,
|
|
56
|
-
:public_instance_methods => 2,
|
|
57
|
-
:public_method_defined? => 2,
|
|
58
|
-
:remove_method => 2,
|
|
59
|
-
:send => 3,
|
|
60
|
-
:undef_method => 2)
|
|
61
50
|
|
|
51
|
+
SCORES.merge!(:alias_method => 2,
|
|
52
|
+
:extend => 2,
|
|
53
|
+
:include => 2,
|
|
54
|
+
:instance_method => 2,
|
|
55
|
+
:instance_methods => 2,
|
|
56
|
+
:method_added => 2,
|
|
57
|
+
:method_defined? => 2,
|
|
58
|
+
:method_removed => 2,
|
|
59
|
+
:method_undefined => 2,
|
|
60
|
+
:private_class_method => 2,
|
|
61
|
+
:private_instance_methods => 2,
|
|
62
|
+
:private_method_defined? => 2,
|
|
63
|
+
:protected_instance_methods => 2,
|
|
64
|
+
:protected_method_defined? => 2,
|
|
65
|
+
:public_class_method => 2,
|
|
66
|
+
:public_instance_methods => 2,
|
|
67
|
+
:public_method_defined? => 2,
|
|
68
|
+
:remove_method => 2,
|
|
69
|
+
:send => 3,
|
|
70
|
+
:undef_method => 2)
|
|
71
|
+
|
|
72
|
+
##
|
|
62
73
|
# calls I don't like and usually see being abused
|
|
74
|
+
|
|
63
75
|
SCORES.merge!(:inject => 2)
|
|
64
76
|
|
|
65
77
|
@@no_class = :main
|
|
@@ -81,16 +93,31 @@ class Flog < SexpProcessor
|
|
|
81
93
|
@calls["#{self.klass_name}##{self.method_name}"][name] += score * @multiplier
|
|
82
94
|
end
|
|
83
95
|
|
|
96
|
+
##
|
|
97
|
+
# For the duration of the block the complexity factor is increased
|
|
98
|
+
# by #bonus This allows the complexity of sub-expressions to be
|
|
99
|
+
# influenced by the expressions in which they are found. Yields 42
|
|
100
|
+
# to the supplied block.
|
|
101
|
+
|
|
84
102
|
def bad_dog! bonus
|
|
85
103
|
@multiplier += bonus
|
|
86
104
|
yield 42
|
|
87
105
|
@multiplier -= bonus
|
|
88
106
|
end
|
|
89
107
|
|
|
108
|
+
##
|
|
109
|
+
# process each element of #exp in turn.
|
|
110
|
+
|
|
90
111
|
def bleed exp
|
|
91
112
|
process exp.shift until exp.empty?
|
|
92
113
|
end
|
|
93
114
|
|
|
115
|
+
##
|
|
116
|
+
# Process #files with flog, recursively descending directories.
|
|
117
|
+
#--
|
|
118
|
+
# There is no way to exclude directories at present (RCS, SCCS, .svn)
|
|
119
|
+
#++
|
|
120
|
+
|
|
94
121
|
def flog_files *files
|
|
95
122
|
files.flatten.each do |file|
|
|
96
123
|
if File.directory? file then
|
|
@@ -103,10 +130,12 @@ class Flog < SexpProcessor
|
|
|
103
130
|
process Sexp.from_array(sexp).first
|
|
104
131
|
rescue SyntaxError => e
|
|
105
132
|
if e.inspect =~ /<%|%>/ then
|
|
106
|
-
warn e.inspect
|
|
133
|
+
warn "#{e.inspect} at #{e.backtrace.first(5).join(', ')}"
|
|
107
134
|
warn "...stupid lemmings and their bad erb templates... skipping"
|
|
108
135
|
else
|
|
109
|
-
raise e
|
|
136
|
+
raise e unless $c
|
|
137
|
+
warn file
|
|
138
|
+
warn "#{e.inspect} at #{e.backtrace.first(5).join(', ')}"
|
|
110
139
|
end
|
|
111
140
|
end
|
|
112
141
|
end
|
|
@@ -119,40 +148,65 @@ class Flog < SexpProcessor
|
|
|
119
148
|
@klasses.shift
|
|
120
149
|
end
|
|
121
150
|
|
|
151
|
+
##
|
|
152
|
+
# returns the first class in the list, or @@no_class if there are
|
|
153
|
+
# none.
|
|
154
|
+
|
|
122
155
|
def klass_name
|
|
123
|
-
@klasses.first || @@no_class
|
|
156
|
+
name = @klasses.first || @@no_class
|
|
157
|
+
if Sexp === name then
|
|
158
|
+
case name.first
|
|
159
|
+
when :colon2 then
|
|
160
|
+
name = name.flatten
|
|
161
|
+
name.delete :const
|
|
162
|
+
name.delete :colon2
|
|
163
|
+
name = name.join("::")
|
|
164
|
+
when :colon3 then
|
|
165
|
+
name = name.last
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
name
|
|
124
169
|
end
|
|
125
170
|
|
|
171
|
+
##
|
|
172
|
+
# Adds name to the list of methods, for the duration of the block
|
|
173
|
+
|
|
126
174
|
def method name
|
|
127
175
|
@methods.unshift name
|
|
128
176
|
yield
|
|
129
177
|
@methods.shift
|
|
130
178
|
end
|
|
131
179
|
|
|
180
|
+
##
|
|
181
|
+
# returns the first method in the list, or @@no_method if there are
|
|
182
|
+
# none.
|
|
183
|
+
|
|
132
184
|
def method_name
|
|
133
185
|
@methods.first || @@no_method
|
|
134
186
|
end
|
|
135
187
|
|
|
188
|
+
##
|
|
189
|
+
# Report results to #io, STDOUT by default.
|
|
190
|
+
|
|
136
191
|
def report io = $stdout
|
|
137
192
|
current = 0
|
|
193
|
+
totals = self.totals
|
|
138
194
|
total_score = self.total
|
|
139
195
|
max = total_score * THRESHOLD
|
|
140
|
-
totals = self.totals
|
|
141
|
-
|
|
142
|
-
if $s then
|
|
143
|
-
io.puts total_score
|
|
144
|
-
exit 0
|
|
145
|
-
end
|
|
146
196
|
|
|
147
|
-
io.puts "Total
|
|
197
|
+
io.puts "Total Flog = %.1f (%.1f +/- %.1f flog / method)" % [total_score, self.average, self.stddev]
|
|
148
198
|
io.puts
|
|
149
199
|
|
|
200
|
+
exit 0 if $s
|
|
201
|
+
|
|
150
202
|
@calls.sort_by { |k,v| -totals[k] }.each do |klass_method, calls|
|
|
203
|
+
next if $m and klass_method =~ /##{@@no_method}/
|
|
151
204
|
total = totals[klass_method]
|
|
152
205
|
io.puts "%s: (%.1f)" % [klass_method, total]
|
|
206
|
+
next if $q
|
|
153
207
|
calls.sort_by { |k,v| -v }.each do |call, count|
|
|
154
208
|
io.puts " %6.1f: %s" % [count, call]
|
|
155
|
-
end
|
|
209
|
+
end unless $n
|
|
156
210
|
|
|
157
211
|
current += total
|
|
158
212
|
break if current >= max
|
|
@@ -162,22 +216,23 @@ class Flog < SexpProcessor
|
|
|
162
216
|
end
|
|
163
217
|
|
|
164
218
|
def reset
|
|
165
|
-
|
|
219
|
+
# TODO: rename @totals
|
|
220
|
+
@totals = @total = nil
|
|
166
221
|
@multiplier = 1.0
|
|
167
222
|
@calls = Hash.new { |h,k| h[k] = Hash.new 0 }
|
|
168
223
|
end
|
|
169
224
|
|
|
170
|
-
|
|
171
|
-
self.totals unless @total_score # calculates total_score as well
|
|
225
|
+
attr_reader :total, :average, :stddev
|
|
172
226
|
|
|
173
|
-
|
|
174
|
-
|
|
227
|
+
##
|
|
228
|
+
# Return the total score and populates @totals.
|
|
175
229
|
|
|
176
230
|
def totals
|
|
177
231
|
unless @totals then
|
|
178
|
-
@
|
|
232
|
+
@total = 0
|
|
179
233
|
@totals = Hash.new(0)
|
|
180
234
|
self.calls.each do |meth, tally|
|
|
235
|
+
next if $m and meth =~ /##{@@no_method}$/
|
|
181
236
|
a, b, c = 0, 0, 0
|
|
182
237
|
tally.each do |cat, score|
|
|
183
238
|
case cat
|
|
@@ -188,9 +243,17 @@ class Flog < SexpProcessor
|
|
|
188
243
|
end
|
|
189
244
|
score = Math.sqrt(a*a + b*b + c*c)
|
|
190
245
|
@totals[meth] = score
|
|
191
|
-
@
|
|
246
|
+
@total += score
|
|
192
247
|
end
|
|
193
248
|
end
|
|
249
|
+
|
|
250
|
+
size = self.calls.size.to_f
|
|
251
|
+
@average = @total / size
|
|
252
|
+
|
|
253
|
+
sum = 0
|
|
254
|
+
@totals.values.each { |i| sum += (i - @average) ** 2 }
|
|
255
|
+
@stddev = (1 / size * sum)
|
|
256
|
+
|
|
194
257
|
@totals
|
|
195
258
|
end
|
|
196
259
|
|
|
@@ -212,6 +275,7 @@ class Flog < SexpProcessor
|
|
|
212
275
|
end
|
|
213
276
|
s()
|
|
214
277
|
end
|
|
278
|
+
alias :process_or :process_and
|
|
215
279
|
|
|
216
280
|
def process_attrasgn(exp)
|
|
217
281
|
add_to_score :assignment, OTHER_SCORES[:assignment]
|
|
@@ -234,7 +298,6 @@ class Flog < SexpProcessor
|
|
|
234
298
|
s()
|
|
235
299
|
end
|
|
236
300
|
|
|
237
|
-
# [:block_pass, [:lit, :blah], [:fcall, :foo]]
|
|
238
301
|
def process_block_pass(exp)
|
|
239
302
|
arg = exp.shift
|
|
240
303
|
call = exp.shift
|
|
@@ -298,6 +361,8 @@ class Flog < SexpProcessor
|
|
|
298
361
|
process exp.shift # assigment, if any
|
|
299
362
|
s()
|
|
300
363
|
end
|
|
364
|
+
alias :process_iasgn :process_dasgn_curr
|
|
365
|
+
alias :process_lasgn :process_dasgn_curr
|
|
301
366
|
|
|
302
367
|
def process_defn(exp)
|
|
303
368
|
self.method exp.shift do
|
|
@@ -321,13 +386,8 @@ class Flog < SexpProcessor
|
|
|
321
386
|
end
|
|
322
387
|
s()
|
|
323
388
|
end
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
add_to_score :assignment, OTHER_SCORES[:assignment]
|
|
327
|
-
exp.shift # name
|
|
328
|
-
process exp.shift # rhs
|
|
329
|
-
s()
|
|
330
|
-
end
|
|
389
|
+
alias :process_rescue :process_else
|
|
390
|
+
alias :process_when :process_else
|
|
331
391
|
|
|
332
392
|
def process_if(exp)
|
|
333
393
|
add_to_score :branch, OTHER_SCORES[:branch]
|
|
@@ -343,7 +403,8 @@ class Flog < SexpProcessor
|
|
|
343
403
|
context = (self.context - [:class, :module, :scope])
|
|
344
404
|
if context.uniq.sort_by {|s|s.to_s} == [:block, :iter] then
|
|
345
405
|
recv = exp.first
|
|
346
|
-
if recv[0] == :call and recv[1] == nil and recv.arglist[1] and
|
|
406
|
+
if (recv[0] == :call and recv[1] == nil and recv.arglist[1] and
|
|
407
|
+
[:lit, :str].include? recv.arglist[1][0]) then
|
|
347
408
|
msg = recv[2]
|
|
348
409
|
submsg = recv.arglist[1][1]
|
|
349
410
|
self.method submsg do
|
|
@@ -366,13 +427,6 @@ class Flog < SexpProcessor
|
|
|
366
427
|
s()
|
|
367
428
|
end
|
|
368
429
|
|
|
369
|
-
def process_lasgn(exp)
|
|
370
|
-
add_to_score :assignment, OTHER_SCORES[:assignment]
|
|
371
|
-
exp.shift # name
|
|
372
|
-
process exp.shift # rhs
|
|
373
|
-
s()
|
|
374
|
-
end
|
|
375
|
-
|
|
376
430
|
def process_lit(exp)
|
|
377
431
|
value = exp.shift
|
|
378
432
|
case value
|
|
@@ -390,8 +444,7 @@ class Flog < SexpProcessor
|
|
|
390
444
|
|
|
391
445
|
def process_masgn(exp)
|
|
392
446
|
add_to_score :assignment, OTHER_SCORES[:assignment]
|
|
393
|
-
|
|
394
|
-
process exp.shift # rhs
|
|
447
|
+
bleed exp
|
|
395
448
|
s()
|
|
396
449
|
end
|
|
397
450
|
|
|
@@ -402,23 +455,6 @@ class Flog < SexpProcessor
|
|
|
402
455
|
s()
|
|
403
456
|
end
|
|
404
457
|
|
|
405
|
-
def process_or(exp)
|
|
406
|
-
add_to_score :branch, OTHER_SCORES[:branch]
|
|
407
|
-
bad_dog! 0.1 do
|
|
408
|
-
process exp.shift # lhs
|
|
409
|
-
process exp.shift # rhs
|
|
410
|
-
end
|
|
411
|
-
s()
|
|
412
|
-
end
|
|
413
|
-
|
|
414
|
-
def process_rescue(exp)
|
|
415
|
-
add_to_score :branch, OTHER_SCORES[:branch]
|
|
416
|
-
bad_dog! 0.1 do
|
|
417
|
-
bleed exp
|
|
418
|
-
end
|
|
419
|
-
s()
|
|
420
|
-
end
|
|
421
|
-
|
|
422
458
|
def process_sclass(exp)
|
|
423
459
|
bad_dog! 0.5 do
|
|
424
460
|
recv = process exp.shift
|
|
@@ -435,24 +471,6 @@ class Flog < SexpProcessor
|
|
|
435
471
|
s()
|
|
436
472
|
end
|
|
437
473
|
|
|
438
|
-
def process_until(exp)
|
|
439
|
-
add_to_score :branch, OTHER_SCORES[:branch]
|
|
440
|
-
bad_dog! 0.1 do
|
|
441
|
-
process exp.shift # cond
|
|
442
|
-
process exp.shift # body
|
|
443
|
-
end
|
|
444
|
-
exp.shift # pre/post
|
|
445
|
-
s()
|
|
446
|
-
end
|
|
447
|
-
|
|
448
|
-
def process_when(exp)
|
|
449
|
-
add_to_score :branch, OTHER_SCORES[:branch]
|
|
450
|
-
bad_dog! 0.1 do
|
|
451
|
-
bleed exp
|
|
452
|
-
end
|
|
453
|
-
s()
|
|
454
|
-
end
|
|
455
|
-
|
|
456
474
|
def process_while(exp)
|
|
457
475
|
add_to_score :branch, OTHER_SCORES[:branch]
|
|
458
476
|
bad_dog! 0.1 do
|
|
@@ -462,6 +480,7 @@ class Flog < SexpProcessor
|
|
|
462
480
|
exp.shift # pre/post
|
|
463
481
|
s()
|
|
464
482
|
end
|
|
483
|
+
alias :process_until :process_while
|
|
465
484
|
|
|
466
485
|
def process_yield(exp)
|
|
467
486
|
add_to_score :yield, OTHER_SCORES[:yield]
|
data/unpack.rb
CHANGED
|
File without changes
|
data/update_scores.rb
CHANGED
|
@@ -1,70 +1,63 @@
|
|
|
1
|
-
#!/usr/
|
|
1
|
+
#!/usr/bin/env ruby -ws
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
# Update the flog scores for a specific set of gems.
|
|
4
|
+
|
|
5
|
+
$: << 'lib' << '../../ParseTree/dev/lib'
|
|
6
|
+
$:.unshift File.expand_path("~/Work/svn/rubygems/lib")
|
|
7
|
+
|
|
8
|
+
require 'yaml'
|
|
5
9
|
require 'flog'
|
|
6
|
-
require '
|
|
10
|
+
require 'gem_updater'
|
|
7
11
|
|
|
8
12
|
$u ||= false
|
|
9
13
|
$f ||= false
|
|
10
14
|
|
|
11
|
-
$score_file
|
|
12
|
-
$misc_error
|
|
13
|
-
$syntax_error =
|
|
14
|
-
$
|
|
15
|
-
$no_gem = [-4]
|
|
15
|
+
$score_file = '../dev/scores.yml'
|
|
16
|
+
$misc_error = {:total => -1, :average => -1, :methods => {}}
|
|
17
|
+
$syntax_error = {:total => -2, :average => -2, :methods => {}}
|
|
18
|
+
$no_gem = {:total => -4, :average => -4, :methods => {}}
|
|
16
19
|
|
|
17
|
-
max
|
|
20
|
+
max = (ARGV.shift || 10).to_i
|
|
18
21
|
|
|
19
22
|
scores = YAML.load(File.read($score_file)) rescue {}
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
##
|
|
25
|
+
# Save the scores in $score_file.
|
|
26
|
+
#--
|
|
27
|
+
# Creates a new file, then renames to overwrite the old one.
|
|
28
|
+
# Wouldn't it be better to copy the old one, then create a new
|
|
29
|
+
# one so you can do a diff?
|
|
30
|
+
#++
|
|
31
|
+
|
|
32
|
+
def save_scores scores
|
|
33
|
+
File.open("#{$score_file}.new", 'w') do |f|
|
|
34
|
+
warn "*** saving scores"
|
|
35
|
+
YAML.dump scores, f
|
|
36
|
+
end
|
|
37
|
+
File.rename "#{$score_file}.new", $score_file
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
GemUpdater::stupid_gems.each do|p|
|
|
27
41
|
scores[p] = $no_gem.dup
|
|
28
42
|
end
|
|
29
43
|
|
|
30
|
-
|
|
44
|
+
GemUpdater::initialize_dir
|
|
31
45
|
|
|
32
46
|
if $u then
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
Dir.chdir "../gems" do
|
|
36
|
-
cache = Gem::SourceInfoCache.cache_data['http://gems.rubyforge.org']
|
|
37
|
-
|
|
38
|
-
gems = Dir["*.gem"]
|
|
39
|
-
old = gems - cache.source_index.latest_specs.values.map { |spec|
|
|
40
|
-
"#{spec.full_name}.gem"
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
puts "deleting #{old.size} gems"
|
|
44
|
-
old.each do |gem|
|
|
45
|
-
scores.delete gem
|
|
46
|
-
File.unlink gem
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
new = cache.source_index.latest_specs.map { |name, spec|
|
|
50
|
-
"#{spec.full_name}.gem"
|
|
51
|
-
} - gems
|
|
52
|
-
|
|
53
|
-
puts "fetching #{new.size} gems"
|
|
54
|
-
new.each do |gem|
|
|
55
|
-
next if scores[gem] == $no_gem unless $f # FIX
|
|
56
|
-
unless system "wget http://gems.rubyforge.org/gems/#{gem}" then
|
|
57
|
-
scores[gem] = $no_gem
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
47
|
+
GemUpdater.update_gem_tarballs
|
|
48
|
+
exit 1
|
|
61
49
|
end
|
|
62
50
|
|
|
63
|
-
my_projects = Regexp.union("InlineFortran", "ParseTree", "RubyInline",
|
|
51
|
+
my_projects = Regexp.union("InlineFortran", "ParseTree", "RubyInline",
|
|
52
|
+
"RubyToC", "ZenHacks", "ZenTest", "bfts",
|
|
53
|
+
"box_layout", "flog", "heckle", "hoe",
|
|
54
|
+
"image_science", "miniunit", "png", "ruby2ruby",
|
|
55
|
+
"rubyforge", "vlad", "zentest")
|
|
64
56
|
|
|
65
57
|
$owners = {}
|
|
66
|
-
|
|
67
|
-
|
|
58
|
+
|
|
59
|
+
GemUpdater.get_latest_gems.each do |spec|
|
|
60
|
+
name = spec.name
|
|
68
61
|
owner = spec.authors.compact
|
|
69
62
|
owner = Array(spec.email) if owner.empty?
|
|
70
63
|
owner.map! { |o| o.sub(/\s*[^ \w@.].*$/, '') }
|
|
@@ -73,17 +66,22 @@ cache['http://gems.rubyforge.org'].source_index.latest_specs.map { |name, spec|
|
|
|
73
66
|
# because we screwed these up back before hoe
|
|
74
67
|
owner << "Eric Hodel" if name =~ /bfts|RubyToC|ParseTree|heckle/
|
|
75
68
|
|
|
76
|
-
$owners["#{spec.full_name}.
|
|
77
|
-
|
|
69
|
+
$owners["#{spec.full_name}.tgz"] = owner.uniq || 'omg I have no idea'
|
|
70
|
+
end
|
|
78
71
|
|
|
79
72
|
def score_for dir
|
|
80
73
|
files = `find #{dir} -name \\*.rb | grep -v gen.*templ`.split(/\n/)
|
|
81
74
|
|
|
82
75
|
flogger = Flog.new
|
|
83
76
|
flogger.flog_files files
|
|
84
|
-
methods = flogger.totals.reject { |k,v| k =~ /\#none$/ }
|
|
85
|
-
|
|
86
|
-
|
|
77
|
+
methods = flogger.totals.reject { |k,v| k =~ /\#none$/ }
|
|
78
|
+
{
|
|
79
|
+
:total => flogger.total,
|
|
80
|
+
:size => methods.size,
|
|
81
|
+
:average => flogger.average,
|
|
82
|
+
:stddev => flogger.stddev,
|
|
83
|
+
:methods => methods
|
|
84
|
+
}
|
|
87
85
|
rescue SyntaxError => e
|
|
88
86
|
warn e.inspect + " at " + e.backtrace.first(5).join(', ') if $v
|
|
89
87
|
$syntax_error.dup
|
|
@@ -92,44 +90,40 @@ rescue => e
|
|
|
92
90
|
$misc_error.dup
|
|
93
91
|
end
|
|
94
92
|
|
|
95
|
-
|
|
96
|
-
File.open("#{$score_file}.new", 'w') do |f|
|
|
97
|
-
warn "*** saving scores"
|
|
98
|
-
YAML.dump scores, f
|
|
99
|
-
end
|
|
100
|
-
File.rename "#{$score_file}.new", $score_file
|
|
101
|
-
end
|
|
102
|
-
|
|
93
|
+
# extract all the gems and process the data for them.
|
|
103
94
|
begin
|
|
104
95
|
dirty = false
|
|
105
96
|
Dir.chdir "../gems" do
|
|
106
|
-
Dir["*.
|
|
97
|
+
Dir["*.tgz"].each_with_index do |gem, i|
|
|
107
98
|
project = File.basename gem
|
|
108
|
-
next if scores.has_key? project unless $f and scores[project][
|
|
99
|
+
next if scores.has_key? project unless $f and scores[project][:total] < 0
|
|
109
100
|
dirty = true
|
|
110
101
|
begin
|
|
111
102
|
warn gem
|
|
112
|
-
dir = gem.sub(/\.
|
|
113
|
-
|
|
103
|
+
dir = gem.sub(/\.tgz$/, '')
|
|
104
|
+
|
|
105
|
+
system "tar -zmxf #{gem} 2> /dev/null"
|
|
106
|
+
|
|
114
107
|
Dir.chdir dir do
|
|
115
|
-
system "(tar -Oxf ../#{gem} data.tar.gz | tar zxf -) 2> /dev/null"
|
|
116
108
|
system "chmod -R a+r ."
|
|
117
109
|
scores[project] = score_for(File.directory?('lib') ? 'lib' : '.')
|
|
118
110
|
end
|
|
119
111
|
ensure
|
|
120
112
|
system "rm -rf #{dir}"
|
|
121
113
|
end
|
|
122
|
-
|
|
123
|
-
if i % 500 == 0 then
|
|
124
|
-
save_scores scores
|
|
125
|
-
end
|
|
126
114
|
end
|
|
127
115
|
end
|
|
128
116
|
ensure
|
|
129
117
|
save_scores scores if dirty
|
|
130
118
|
end
|
|
131
119
|
|
|
132
|
-
scores.reject! { |k,v| v.
|
|
120
|
+
scores.reject! { |k,v| v[:total].nil? or v[:methods].empty? }
|
|
121
|
+
|
|
122
|
+
class Hash
|
|
123
|
+
def sorted_methods
|
|
124
|
+
self[:methods].sort_by { |k,v| -v }
|
|
125
|
+
end
|
|
126
|
+
end
|
|
133
127
|
|
|
134
128
|
class Array
|
|
135
129
|
def sum
|
|
@@ -170,13 +164,13 @@ def report title, data
|
|
|
170
164
|
end
|
|
171
165
|
end
|
|
172
166
|
|
|
173
|
-
project_numbers = scores.map { |k,v| [k, v[
|
|
167
|
+
project_numbers = scores.map { |k,v| [k, v[:methods].map {|_,n| n}.flatten] }
|
|
174
168
|
project_stats = project_numbers.map { |k,v| [k, v.size, v.average, v.stddev] }
|
|
175
169
|
|
|
176
170
|
title "Statistics" do
|
|
177
|
-
flog_numbers = scores.map { |k,v| v
|
|
178
|
-
all_scores = scores.map { |k,v| v[
|
|
179
|
-
method_counts =
|
|
171
|
+
flog_numbers = scores.map { |k,v| v[:total] }
|
|
172
|
+
all_scores = scores.map { |k,v| v[:methods].values }.flatten
|
|
173
|
+
method_counts = scores.map { |k,v| v[:size] }
|
|
180
174
|
|
|
181
175
|
puts "total # gems : %8d" % scores.size
|
|
182
176
|
puts "total # methods : %8d" % all_scores.size
|
|
@@ -194,14 +188,27 @@ def report_worst section, data
|
|
|
194
188
|
end
|
|
195
189
|
end
|
|
196
190
|
|
|
197
|
-
worst = scores.sort_by { |k,v| -v
|
|
191
|
+
worst = scores.sort_by { |k,v| -v[:total] }.first(max)
|
|
198
192
|
report_worst "Worst Projects EVAR", worst do |project, score|
|
|
199
|
-
|
|
193
|
+
owner = $owners[project].join(', ') rescue nil
|
|
194
|
+
raise "#{project} seems not to have an owner" if owner.nil?
|
|
195
|
+
[score[:total], project, owner]
|
|
200
196
|
end
|
|
201
197
|
|
|
202
|
-
worst =
|
|
203
|
-
|
|
204
|
-
|
|
198
|
+
worst = {}
|
|
199
|
+
scores.each do |long_name, spec|
|
|
200
|
+
name = long_name.sub(/-(\d+\.)*\d+\.gem$/, '')
|
|
201
|
+
spec[:methods].each do |method_name, score|
|
|
202
|
+
worst[[name, method_name]] = score
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
worst = worst.sort_by { |_,v| -v }.first(max)
|
|
207
|
+
|
|
208
|
+
max_size = worst.map { |(name, meth), score| name.size }.max
|
|
209
|
+
title "Worth Methods EVAR"
|
|
210
|
+
worst.each_with_index do |((name, meth), score), i|
|
|
211
|
+
puts "%3d: %9.2f: %-#{max_size}s %s" % [i + 1, score, name, meth]
|
|
205
212
|
end
|
|
206
213
|
|
|
207
214
|
report "Methods per Gem", project_stats.sort_by { |n, c, a, sd| -c }.first(max)
|
|
@@ -212,7 +219,7 @@ $projects_per_owner = Hash.new { |h,k| h[k] = {} }
|
|
|
212
219
|
$owners.each do |project, owners|
|
|
213
220
|
next unless scores.has_key? project # bad project
|
|
214
221
|
owners.each do |owner|
|
|
215
|
-
score = scores[project]
|
|
222
|
+
score = scores[project][:total] || 1000000
|
|
216
223
|
$projects_per_owner[owner][project] = score
|
|
217
224
|
$score_per_owner[owner] += score
|
|
218
225
|
end
|
|
@@ -234,5 +241,5 @@ report_bad_people "Top Flog Scores per Developer" do
|
|
|
234
241
|
end
|
|
235
242
|
|
|
236
243
|
report_bad_people "Most Prolific Developers" do |k,v|
|
|
237
|
-
$projects_per_owner.sort_by { |k,v| -v.size }.first(max)
|
|
244
|
+
$projects_per_owner.sort_by { |k,v| [-v.size, -$score_per_owner[k]] }.first(max)
|
|
238
245
|
end
|
metadata
CHANGED
|
@@ -1,73 +1,94 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
|
-
rubygems_version: 0.9.4
|
|
3
|
-
specification_version: 1
|
|
4
2
|
name: flog
|
|
5
3
|
version: !ruby/object:Gem::Version
|
|
6
|
-
version: 1.
|
|
7
|
-
date: 2007-08-21 00:00:00 -07:00
|
|
8
|
-
summary: Flog reports the most tortured code in an easy to read pain report. The higher the score, the more pain the code is in.
|
|
9
|
-
require_paths:
|
|
10
|
-
- lib
|
|
11
|
-
email: ryand-ruby@zenspider.com
|
|
12
|
-
homepage: http://ruby.sadi.st/
|
|
13
|
-
rubyforge_project: seattlerb
|
|
14
|
-
description: "Flog reports the most tortured code in an easy to read pain report. The higher the score, the more pain the code is in. % ./bin/flog bin/flog Total score = 128.7 Flog#report: (21) 4: puts 2: sort_by ..."
|
|
15
|
-
autorequire:
|
|
16
|
-
default_executable:
|
|
17
|
-
bindir: bin
|
|
18
|
-
has_rdoc: true
|
|
19
|
-
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
|
20
|
-
requirements:
|
|
21
|
-
- - ">"
|
|
22
|
-
- !ruby/object:Gem::Version
|
|
23
|
-
version: 0.0.0
|
|
24
|
-
version:
|
|
4
|
+
version: 1.2.0
|
|
25
5
|
platform: ruby
|
|
26
|
-
signing_key:
|
|
27
|
-
cert_chain:
|
|
28
|
-
post_install_message:
|
|
29
6
|
authors:
|
|
30
7
|
- Ryan Davis
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
- README.txt
|
|
35
|
-
- Rakefile
|
|
36
|
-
- bin/flog
|
|
37
|
-
- lib/flog.rb
|
|
38
|
-
- unpack.rb
|
|
39
|
-
- update_scores.rb
|
|
40
|
-
test_files: []
|
|
41
|
-
|
|
42
|
-
rdoc_options:
|
|
43
|
-
- --main
|
|
44
|
-
- README.txt
|
|
45
|
-
extra_rdoc_files:
|
|
46
|
-
- History.txt
|
|
47
|
-
- Manifest.txt
|
|
48
|
-
- README.txt
|
|
49
|
-
executables:
|
|
50
|
-
- flog
|
|
51
|
-
extensions: []
|
|
52
|
-
|
|
53
|
-
requirements: []
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
54
11
|
|
|
12
|
+
date: 2008-10-22 00:00:00 -05:00
|
|
13
|
+
default_executable:
|
|
55
14
|
dependencies:
|
|
15
|
+
- !ruby/object:Gem::Dependency
|
|
16
|
+
name: sexp_processor
|
|
17
|
+
type: :runtime
|
|
18
|
+
version_requirement:
|
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
20
|
+
requirements:
|
|
21
|
+
- - ~>
|
|
22
|
+
- !ruby/object:Gem::Version
|
|
23
|
+
version: "3.0"
|
|
24
|
+
version:
|
|
56
25
|
- !ruby/object:Gem::Dependency
|
|
57
26
|
name: ParseTree
|
|
27
|
+
type: :runtime
|
|
58
28
|
version_requirement:
|
|
59
|
-
version_requirements: !ruby/object:Gem::
|
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
60
30
|
requirements:
|
|
61
|
-
- -
|
|
31
|
+
- - ~>
|
|
62
32
|
- !ruby/object:Gem::Version
|
|
63
|
-
version:
|
|
33
|
+
version: "3.0"
|
|
64
34
|
version:
|
|
65
35
|
- !ruby/object:Gem::Dependency
|
|
66
36
|
name: hoe
|
|
37
|
+
type: :development
|
|
67
38
|
version_requirement:
|
|
68
|
-
version_requirements: !ruby/object:Gem::
|
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
69
40
|
requirements:
|
|
70
41
|
- - ">="
|
|
71
42
|
- !ruby/object:Gem::Version
|
|
72
|
-
version: 1.
|
|
43
|
+
version: 1.8.0
|
|
73
44
|
version:
|
|
45
|
+
description: Flog reports the most tortured code in an easy to read pain report. The higher the score, the more pain the code is in.
|
|
46
|
+
email:
|
|
47
|
+
- ryand-ruby@zenspider.com
|
|
48
|
+
executables:
|
|
49
|
+
- flog
|
|
50
|
+
extensions: []
|
|
51
|
+
|
|
52
|
+
extra_rdoc_files:
|
|
53
|
+
- History.txt
|
|
54
|
+
- Manifest.txt
|
|
55
|
+
- README.txt
|
|
56
|
+
files:
|
|
57
|
+
- History.txt
|
|
58
|
+
- Manifest.txt
|
|
59
|
+
- README.txt
|
|
60
|
+
- Rakefile
|
|
61
|
+
- bin/flog
|
|
62
|
+
- gem_updater.rb
|
|
63
|
+
- lib/flog.rb
|
|
64
|
+
- unpack.rb
|
|
65
|
+
- update_scores.rb
|
|
66
|
+
has_rdoc: true
|
|
67
|
+
homepage: http://ruby.sadi.st/
|
|
68
|
+
post_install_message:
|
|
69
|
+
rdoc_options:
|
|
70
|
+
- --main
|
|
71
|
+
- README.txt
|
|
72
|
+
require_paths:
|
|
73
|
+
- lib
|
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
75
|
+
requirements:
|
|
76
|
+
- - ">="
|
|
77
|
+
- !ruby/object:Gem::Version
|
|
78
|
+
version: "0"
|
|
79
|
+
version:
|
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
81
|
+
requirements:
|
|
82
|
+
- - ">="
|
|
83
|
+
- !ruby/object:Gem::Version
|
|
84
|
+
version: "0"
|
|
85
|
+
version:
|
|
86
|
+
requirements: []
|
|
87
|
+
|
|
88
|
+
rubyforge_project: seattlerb
|
|
89
|
+
rubygems_version: 1.3.0
|
|
90
|
+
signing_key:
|
|
91
|
+
specification_version: 2
|
|
92
|
+
summary: Flog reports the most tortured code in an easy to read pain report
|
|
93
|
+
test_files: []
|
|
94
|
+
|