aidir 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'aidir'
4
+
5
+ aidir = Aidir::start
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: []