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 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: []