aidir 0.0.1
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.
- checksums.yaml +7 -0
- data/bin/aidir +5 -0
- data/lib/aidir.rb +35 -0
- data/lib/aidir/flog.rb +75 -0
- data/lib/aidir/git.rb +62 -0
- data/lib/aidir/scoreboard.rb +195 -0
- metadata +79 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7742d491ef0024bf96b42dc5702247322aa561cd
|
4
|
+
data.tar.gz: 77c3484dff8c9d897fec772ab81c39824c2b5bfd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8a567fe9d09b8326ba6458f25c6933564c1f831ab6deb118f5711a6fb387585fd70190d55544ed3f8e2cb0c6985194c0ddd7487497ac52242d0e8c31e818e800
|
7
|
+
data.tar.gz: 4816f092e78393dac48ea363ef4dffea115d70583f71eb34926f8c44b4401172bfcc96a7a6a6facacf6bc6ace49e1d2a9e53346e0795fc00717fa480657dd88b
|
data/bin/aidir
ADDED
data/lib/aidir.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'aidir/git'
|
2
|
+
require_relative 'aidir/flog'
|
3
|
+
require_relative 'aidir/scoreboard'
|
4
|
+
require 'open3'
|
5
|
+
|
6
|
+
class Aidir
|
7
|
+
|
8
|
+
def self.start
|
9
|
+
@errors = []
|
10
|
+
@results = {}
|
11
|
+
git = nil
|
12
|
+
files = nil
|
13
|
+
|
14
|
+
git = Git.new(@errors)
|
15
|
+
git.is_repository?
|
16
|
+
if @errors.any?
|
17
|
+
puts @errors
|
18
|
+
return
|
19
|
+
end
|
20
|
+
|
21
|
+
files = git.ruby_files
|
22
|
+
|
23
|
+
files.each do |file|
|
24
|
+
flog = Flog.new(file)
|
25
|
+
@results[file] = flog.analyze
|
26
|
+
end
|
27
|
+
|
28
|
+
git.clear_cached_files
|
29
|
+
|
30
|
+
scoreboard = Scoreboard.new(@results)
|
31
|
+
output = scoreboard.results
|
32
|
+
print output
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/lib/aidir/flog.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
class Flog
|
2
|
+
|
3
|
+
def initialize(filename)
|
4
|
+
@branch = filename
|
5
|
+
@master = temp(filename)
|
6
|
+
@flog_data = {}
|
7
|
+
@results = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def analyze
|
11
|
+
flog_both
|
12
|
+
parse_flog_data
|
13
|
+
@results
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def flog_both
|
19
|
+
@flog_data[:branch] = flog_file(@branch)
|
20
|
+
@flog_data[:master] = flog_file(@master)
|
21
|
+
end
|
22
|
+
|
23
|
+
def parse_flog_data
|
24
|
+
@flog_data.each do |branch, branch_data|
|
25
|
+
data = raw_to_hash(branch_data)
|
26
|
+
data.each do |key, val|
|
27
|
+
@results[key] ||= {}
|
28
|
+
@results[key][branch] = val
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def flog_file(filename)
|
34
|
+
Open3.popen3("flog -a #{filename}") do |_, stdout, stderr|
|
35
|
+
stdout.read
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def raw_to_hash(data)
|
40
|
+
lines = string_to_line_arr(data)
|
41
|
+
lines = values_to_floats(lines)
|
42
|
+
lines[2..-1] = clean_method_names(lines[2..-1]) # clean methods from paths
|
43
|
+
Hash[*lines.flatten]
|
44
|
+
end
|
45
|
+
|
46
|
+
def temp(file)
|
47
|
+
safe_filename = file.gsub('/', '_')
|
48
|
+
"#{Dir.pwd}/tmp/aidir_#{safe_filename}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def string_to_line_arr(string)
|
52
|
+
string.split("\n")
|
53
|
+
.reject { |l| l.empty? }
|
54
|
+
.map! { |l| l.strip.split(": ").reverse }
|
55
|
+
end
|
56
|
+
|
57
|
+
def values_to_floats(lines)
|
58
|
+
lines.map do |line|
|
59
|
+
[
|
60
|
+
line[0],
|
61
|
+
line[1].to_f
|
62
|
+
]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def clean_method_names(lines)
|
67
|
+
lines.map do |line|
|
68
|
+
[
|
69
|
+
line[0].split.first,
|
70
|
+
line[1]
|
71
|
+
]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
data/lib/aidir/git.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
class Git
|
2
|
+
|
3
|
+
def initialize(errors)
|
4
|
+
@errors = errors
|
5
|
+
@changed_files = []
|
6
|
+
end
|
7
|
+
|
8
|
+
def is_repository?
|
9
|
+
error = false
|
10
|
+
Open3.popen3('git rev-parse') do |_, _, stderr|
|
11
|
+
error = stderr.read
|
12
|
+
@errors << error unless error.empty?
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def ruby_files
|
17
|
+
all_changed_files
|
18
|
+
filter_ruby_files
|
19
|
+
cache_files
|
20
|
+
@changed_files
|
21
|
+
end
|
22
|
+
|
23
|
+
def clear_cached_files
|
24
|
+
@changed_files.each do |file|
|
25
|
+
File.delete(temp(file))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def all_changed_files
|
32
|
+
Open3.popen3("git diff --name-only origin/master...") do |_, stdout, stderr|
|
33
|
+
out = stdout.read
|
34
|
+
@changed_files = out.split("\n") unless out.empty?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def filter_ruby_files
|
39
|
+
@changed_files.reject! { |filename| filename[-3..-1] != '.rb' }
|
40
|
+
end
|
41
|
+
|
42
|
+
def cache_files
|
43
|
+
@changed_files.each do |file|
|
44
|
+
File.open(temp(file), 'w') do |f|
|
45
|
+
f.write(remote_file_contents(file))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def remote_file_contents(file)
|
51
|
+
Open3.popen3("git show origin/master:#{file}") do |_, stdout, stderr|
|
52
|
+
stdout.read
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def temp(file)
|
57
|
+
safe_filename = file.gsub('/', '_')
|
58
|
+
"#{Dir.pwd}/tmp/aidir_#{safe_filename}"
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,195 @@
|
|
1
|
+
class Scoreboard
|
2
|
+
|
3
|
+
def initialize(raw_data)
|
4
|
+
@raw_data = raw_data
|
5
|
+
@diff_data = {}
|
6
|
+
@file_data = {}
|
7
|
+
@method_data = {}
|
8
|
+
@output = ''
|
9
|
+
end
|
10
|
+
|
11
|
+
def results
|
12
|
+
get_relevant_scores
|
13
|
+
if @method_data.empty?
|
14
|
+
print_no_diffs
|
15
|
+
return
|
16
|
+
end
|
17
|
+
print_method_board
|
18
|
+
print_file_board
|
19
|
+
@output
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def get_relevant_scores
|
25
|
+
get_diffs
|
26
|
+
split_scores_by_type
|
27
|
+
sort_scores
|
28
|
+
end
|
29
|
+
|
30
|
+
def diff_format
|
31
|
+
@diff_format ||= "%s%18.1f%s"
|
32
|
+
end
|
33
|
+
|
34
|
+
def current_format
|
35
|
+
@current_format ||= "%s%10.1f%s"
|
36
|
+
end
|
37
|
+
|
38
|
+
def diff_output(score)
|
39
|
+
sprintf(diff_format, diff_prefix(score), score, color_end)
|
40
|
+
end
|
41
|
+
|
42
|
+
def current_output(score)
|
43
|
+
sprintf(current_format, current_prefix(score), score, color_end)
|
44
|
+
end
|
45
|
+
|
46
|
+
def total_current_output(score)
|
47
|
+
sprintf(current_format, "", score, "")
|
48
|
+
end
|
49
|
+
|
50
|
+
def avg_current_output(score)
|
51
|
+
sprintf(current_format, current_prefix(score), score, color_end)
|
52
|
+
end
|
53
|
+
|
54
|
+
def head_format
|
55
|
+
@head_format ||= "%18s%10s %-90s\n"
|
56
|
+
end
|
57
|
+
|
58
|
+
def print_method_board
|
59
|
+
@output << "--- #{cyan_start}METHOD SCORES#{color_end} ---\n"
|
60
|
+
|
61
|
+
@output << sprintf(head_format, "Diff from master", "Current", "Method")
|
62
|
+
format = "%s%s %-90s\n"
|
63
|
+
|
64
|
+
@method_data.each do |method, info|
|
65
|
+
current = info[:current]
|
66
|
+
unless info[:flag]
|
67
|
+
diff = info[:diff]
|
68
|
+
@output << sprintf(format, diff_output(diff), current_output(current), method)
|
69
|
+
else
|
70
|
+
flag_output = sprintf("%18s", info[:flag].to_s)
|
71
|
+
@output << sprintf(format, flag_output, current_output(current), method)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def print_file_board
|
77
|
+
@output << "--- #{cyan_start}FILE SCORES#{color_end} ---\n"
|
78
|
+
|
79
|
+
@output << sprintf(head_format, "Diff from master", "Current", "Method")
|
80
|
+
format = "%s%s %-90s\n"
|
81
|
+
|
82
|
+
@file_data.each do |metric, files|
|
83
|
+
@output << sprintf("%-18s\n", "#{cyan_start}#{metric}#{color_end}")
|
84
|
+
files.each do |file|
|
85
|
+
filename = file[:file]
|
86
|
+
diff = file[:diff]
|
87
|
+
current = file[:current]
|
88
|
+
if metric == "flog total"
|
89
|
+
@output << sprintf(format, diff_output(diff), total_current_output(current), filename)
|
90
|
+
else
|
91
|
+
@output << sprintf(format, diff_output(diff), avg_current_output(current), filename)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def print_no_diffs
|
98
|
+
@output << "#{cyan_start}No changes detected#{color_end}\n"
|
99
|
+
end
|
100
|
+
|
101
|
+
def diff_prefix(score)
|
102
|
+
if score < 0
|
103
|
+
green_start
|
104
|
+
elsif score < 5
|
105
|
+
yellow_start
|
106
|
+
else
|
107
|
+
red_start
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def current_prefix(score)
|
112
|
+
if score < 20
|
113
|
+
green_start
|
114
|
+
elsif score < 40
|
115
|
+
yellow_start
|
116
|
+
else
|
117
|
+
red_start
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def cyan_start
|
122
|
+
"\033[36m"
|
123
|
+
end
|
124
|
+
|
125
|
+
def red_start
|
126
|
+
"\033[31m"
|
127
|
+
end
|
128
|
+
|
129
|
+
def yellow_start
|
130
|
+
"\033[33m"
|
131
|
+
end
|
132
|
+
|
133
|
+
def green_start
|
134
|
+
"\033[32m"
|
135
|
+
end
|
136
|
+
|
137
|
+
def color_end
|
138
|
+
"\033[0m"
|
139
|
+
end
|
140
|
+
|
141
|
+
def split_scores_by_type
|
142
|
+
@method_data = @diff_data
|
143
|
+
file_keys.each do |key|
|
144
|
+
@file_data[key] = @method_data.delete(key)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def get_diffs
|
149
|
+
@raw_data.each do |file, lines|
|
150
|
+
lines.each do |metric, scores|
|
151
|
+
score = diff(scores[:branch], scores[:master])
|
152
|
+
next if score == 0.0
|
153
|
+
@diff_data[metric] ||= []
|
154
|
+
flag = nil
|
155
|
+
if [:new, :deleted].include?(score)
|
156
|
+
flag = score
|
157
|
+
score = 0.0
|
158
|
+
end
|
159
|
+
@diff_data[metric] << {
|
160
|
+
file: file,
|
161
|
+
diff: score,
|
162
|
+
current: scores[:branch],
|
163
|
+
flag: flag
|
164
|
+
}
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def sort_scores
|
170
|
+
return if @method_data.empty?
|
171
|
+
file_keys.each do |key|
|
172
|
+
@file_data[key].sort_by! { |f| -f[:diff] }
|
173
|
+
end
|
174
|
+
sorted_methods = @method_data.sort_by { |_, data| -data[0][:diff] }.flatten
|
175
|
+
@method_data = Hash[*sorted_methods]
|
176
|
+
end
|
177
|
+
|
178
|
+
def diff(branch, master)
|
179
|
+
if master and branch
|
180
|
+
(branch - master).round(2)
|
181
|
+
elsif branch
|
182
|
+
:new
|
183
|
+
else
|
184
|
+
:deleted
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def file_keys
|
189
|
+
[
|
190
|
+
'flog total',
|
191
|
+
'flog/method average'
|
192
|
+
]
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: aidir
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Adomas Sliužinskas
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-10-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: flog
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 4.1.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 4.1.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: flog
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 4.1.2
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 4.1.2
|
41
|
+
description: 'aidir - Am I Doing It Right: track and improve your Flog (http://ruby.sadi.st/Flog.html)
|
42
|
+
score before merging code to master by getting Flog score differences between current
|
43
|
+
branch and master branch'
|
44
|
+
email: adomas.sliuzinskas@gmail.com
|
45
|
+
executables:
|
46
|
+
- aidir
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- lib/aidir.rb
|
51
|
+
- lib/aidir/flog.rb
|
52
|
+
- lib/aidir/git.rb
|
53
|
+
- lib/aidir/scoreboard.rb
|
54
|
+
- bin/aidir
|
55
|
+
homepage: http://github.com/adomas-s/aidir
|
56
|
+
licenses:
|
57
|
+
- MIT
|
58
|
+
metadata: {}
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
requirements: []
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 2.0.3
|
76
|
+
signing_key:
|
77
|
+
specification_version: 4
|
78
|
+
summary: Shows Flog score diff of current git branch vs. origin/master
|
79
|
+
test_files: []
|