pair_see 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +98 -0
- data/.travis.yml +4 -0
- data/CHANGELOG.md +8 -0
- data/README.md +35 -43
- data/Rakefile +1 -1
- data/TODO.md +3 -20
- data/bin/bundler +7 -6
- data/bin/cc-tddium-post-worker +7 -6
- data/bin/coderay +7 -6
- data/bin/console +0 -0
- data/bin/htmldiff +7 -6
- data/bin/ldiff +7 -6
- data/bin/pairsee +22 -8
- data/bin/pry +7 -6
- data/bin/rake +7 -6
- data/bin/rake_commit +7 -6
- data/bin/rspec +7 -6
- data/bin/rubocop +7 -6
- data/bin/ruby-parse +7 -6
- data/bin/ruby-rewrite +7 -6
- data/config/config.yml.example +11 -0
- data/lib/pair_see.rb +1 -1
- data/lib/pair_see/active_devs.rb +3 -12
- data/lib/pair_see/card.rb +5 -4
- data/lib/pair_see/card_knowledge_summary.rb +25 -0
- data/lib/pair_see/cards_per_person.rb +35 -25
- data/lib/pair_see/date_combo.rb +2 -1
- data/lib/pair_see/knowledge_debt.rb +31 -0
- data/lib/pair_see/log_line.rb +38 -40
- data/lib/pair_see/log_line_parse.rb +24 -0
- data/lib/pair_see/log_lines.rb +6 -10
- data/lib/pair_see/{combo.rb → pair_commit_count.rb} +3 -2
- data/lib/pair_see/pair_recency.rb +27 -0
- data/lib/pair_see/pairing_event.rb +24 -0
- data/lib/pair_see/person.rb +0 -1
- data/lib/pair_see/seer.rb +25 -101
- data/lib/pair_see/too_much_stuff.rb +157 -0
- data/lib/pair_see/version.rb +1 -1
- data/pair_see.gemspec +1 -0
- metadata +13 -5
- data/config/config.yml.sample +0 -8
@@ -0,0 +1,24 @@
|
|
1
|
+
module PairSee
|
2
|
+
class LogLineParse
|
3
|
+
require_relative 'log_lines'
|
4
|
+
require 'git'
|
5
|
+
|
6
|
+
@@maximum_commits_to_parse = 9999
|
7
|
+
attr_reader :log_lines
|
8
|
+
|
9
|
+
def initialize(roots, date_string)
|
10
|
+
@log_lines = _parse(date_string, roots)
|
11
|
+
end
|
12
|
+
|
13
|
+
def _parse(date_string, roots)
|
14
|
+
lines = []
|
15
|
+
roots.each do |root|
|
16
|
+
g = Git.open(root)
|
17
|
+
lines << g.log(@@maximum_commits_to_parse).since(date_string).map do |l|
|
18
|
+
LogLine.new("#{l.date} #{l.message}")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
LogLines.new(lines.flatten)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/pair_see/log_lines.rb
CHANGED
@@ -10,11 +10,11 @@ module PairSee
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def each(&block)
|
13
|
-
lines.each &block
|
13
|
+
@lines.each &block
|
14
14
|
end
|
15
15
|
|
16
16
|
def last
|
17
|
-
lines.last
|
17
|
+
@lines.last
|
18
18
|
end
|
19
19
|
|
20
20
|
def active?(person)
|
@@ -24,21 +24,17 @@ module PairSee
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def commits_for_pair(person1, person2)
|
27
|
-
select {|log_line| log_line.authored_by?(person1, person2)}
|
27
|
+
select { |log_line| log_line.authored_by?(person1, person2) }
|
28
28
|
end
|
29
29
|
|
30
|
-
def
|
31
|
-
reject {|log_line| log_line.by_any? devs}
|
30
|
+
def commits_not_by_known_person(devs)
|
31
|
+
reject { |log_line| log_line.by_any? devs }
|
32
32
|
end
|
33
33
|
|
34
34
|
def solo_commits(people, person)
|
35
35
|
select do |log_line|
|
36
|
-
log_line.authored_by?(person) && (people - [person]).none? {|single_person| log_line.authored_by?(single_person)}
|
36
|
+
log_line.authored_by?(person) && (people - [person]).none? { |single_person| log_line.authored_by?(single_person) }
|
37
37
|
end
|
38
38
|
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
attr_reader :lines
|
43
39
|
end
|
44
40
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module PairSee
|
2
|
+
class PairRecency
|
3
|
+
def initialize(log_lines, card_prefixes, people)
|
4
|
+
@log_lines = log_lines
|
5
|
+
@card_prefixes = card_prefixes
|
6
|
+
@people = people
|
7
|
+
end
|
8
|
+
|
9
|
+
def pair_recency
|
10
|
+
pairing_events = @people.map do |current_person|
|
11
|
+
my_commits = @log_lines.select { |ll| ll.authored_by?(current_person) }
|
12
|
+
|
13
|
+
most_recent_commits = {}
|
14
|
+
@people.map do |pair|
|
15
|
+
my_commits.each do |ll|
|
16
|
+
if pair.display_name != current_person.display_name && ll.authored_by?(pair)
|
17
|
+
most_recent_commits[pair] = [ll, pair] # TODO: make [ll, pair] and object? or make ll know devs in ll?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
PairingEvent.new(current_person, most_recent_commits)
|
22
|
+
end
|
23
|
+
|
24
|
+
pairing_events.map(&:pretty) # TODO: make an object which extends Enum and holds pairing events
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module PairSee
|
2
|
+
class PairingEvent
|
3
|
+
def initialize(current_person, most_recent_commits)
|
4
|
+
@current_person = current_person
|
5
|
+
@most_recent_commits = most_recent_commits
|
6
|
+
end
|
7
|
+
|
8
|
+
def pretty
|
9
|
+
@most_recent_commits.sort_by { |_pair, tuple| tuple.first.date }.map do |_pair, tuple|
|
10
|
+
"#{@current_person}, #{tuple.last}: #{tuple.first.date}"
|
11
|
+
end + _pretty_spacing
|
12
|
+
end
|
13
|
+
|
14
|
+
def person
|
15
|
+
@current_person
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def _pretty_spacing
|
21
|
+
['']
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/pair_see/person.rb
CHANGED
data/lib/pair_see/seer.rb
CHANGED
@@ -1,128 +1,52 @@
|
|
1
1
|
module PairSee
|
2
2
|
class Seer
|
3
|
-
|
4
|
-
require_relative 'combo'
|
5
|
-
require_relative 'date_combo'
|
6
|
-
require_relative 'log_lines'
|
7
|
-
require_relative 'card'
|
8
|
-
require_relative 'cards_per_person'
|
9
|
-
require_relative 'active_devs'
|
3
|
+
require_relative 'too_much_stuff'
|
10
4
|
|
11
|
-
attr_reader :
|
12
|
-
@@maximum_commits_to_parse = 9999
|
5
|
+
attr_reader :seer
|
13
6
|
|
14
7
|
def initialize(options)
|
15
|
-
@
|
16
|
-
@
|
17
|
-
@
|
18
|
-
@
|
19
|
-
@
|
20
|
-
@
|
8
|
+
@repo_locations = options[:repo_locations]
|
9
|
+
@after_date = options[:after_date]
|
10
|
+
@card_prefix = options[:card_prefix]
|
11
|
+
@names = options[:names]
|
12
|
+
@seer = PairSee::TooMuchStuff.new(options)
|
13
|
+
@log_lines = LogLineParse.new(@repo_locations, @after_date).log_lines
|
21
14
|
end
|
22
15
|
|
23
|
-
def
|
24
|
-
|
25
|
-
end
|
26
|
-
|
27
|
-
def _lines_from(roots, date_string)
|
28
|
-
lines = []
|
29
|
-
roots.each {|root|
|
30
|
-
g = Git.open(root)
|
31
|
-
lines << g.log(@@maximum_commits_to_parse).since(date_string).map do |l|
|
32
|
-
LogLine.new("#{l.date} #{l.message}")
|
33
|
-
end
|
34
|
-
}
|
35
|
-
LogLines.new(lines.flatten)
|
36
|
-
end
|
37
|
-
|
38
|
-
def pretty_card_data
|
39
|
-
card_data(card_prefixes).map do |card|
|
40
|
-
card.pretty unless card.nil?
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def card_data(card_prefixes)
|
45
|
-
card_prefixes.map do |card_prefix|
|
46
|
-
card_numbers(card_prefix).map do |card_name|
|
47
|
-
commits = commits_on_card(card_name)
|
48
|
-
Card.new(card_name, commits.count, commits.first.date, commits.last.date)
|
49
|
-
end
|
50
|
-
end.flatten.sort_by(&:duration).reverse
|
51
|
-
end
|
52
|
-
|
53
|
-
def commits_on_card(card_name)
|
54
|
-
log_lines.select {|line| line.contains_card_name?(card_name)}
|
55
|
-
end
|
56
|
-
|
57
|
-
def card_numbers(card_prefix)
|
58
|
-
log_lines.select do |line|
|
59
|
-
line.contains_card?(card_prefix)
|
60
|
-
end.map do |line|
|
61
|
-
line.card_name([card_prefix])
|
62
|
-
end.uniq.compact
|
16
|
+
def commits_not_by_known_pair
|
17
|
+
seer.commits_not_by_known_person
|
63
18
|
end
|
64
19
|
|
65
|
-
def
|
66
|
-
|
67
|
-
config['card_prefix']
|
20
|
+
def all_most_recent_commits
|
21
|
+
seer.all_most_recent_commits
|
68
22
|
end
|
69
23
|
|
70
|
-
def
|
71
|
-
|
24
|
+
def recommended_pairings
|
25
|
+
seer.recommended_pairings
|
72
26
|
end
|
73
27
|
|
74
|
-
def
|
75
|
-
|
76
|
-
Combo.new(commits_for_pair(person1, person2).count, person1, person2)
|
77
|
-
end
|
28
|
+
def pretty_card_data
|
29
|
+
seer.pretty_card_data
|
78
30
|
end
|
79
31
|
|
80
|
-
def
|
81
|
-
|
82
|
-
Combo.new(log_lines.solo_commits(devs, dev).count, dev)
|
83
|
-
end
|
32
|
+
def pretty_card_data_by_commits
|
33
|
+
seer.pretty_card_data_by_commits
|
84
34
|
end
|
85
35
|
|
86
36
|
def all_commits
|
87
|
-
|
88
|
-
end
|
89
|
-
|
90
|
-
def commits_for_pair(person1, person2)
|
91
|
-
log_lines.commits_for_pair person1, person2
|
92
|
-
end
|
93
|
-
|
94
|
-
def commits_not_by_known_pair
|
95
|
-
log_lines.commits_not_by_known_pair devs
|
37
|
+
seer.all_commits
|
96
38
|
end
|
97
39
|
|
98
|
-
def
|
99
|
-
|
100
|
-
recent_commit ? recent_commit.date : nil
|
101
|
-
end
|
102
|
-
|
103
|
-
def all_most_recent_commits
|
104
|
-
dev_pairs.map do |person1, person2|
|
105
|
-
DateCombo.new(most_recent_commit_date(person1, person2), person1, person2)
|
106
|
-
end.sort.reverse.map &:to_s
|
107
|
-
end
|
108
|
-
|
109
|
-
def recommended_pairings
|
110
|
-
should_pair = unpaired_in_range
|
111
|
-
should_pair.empty? ? [least_recent_pair] : should_pair
|
40
|
+
def cards_per_person
|
41
|
+
CardsPerPerson.new(@log_lines, @card_prefix, @names).cards_per_person
|
112
42
|
end
|
113
43
|
|
114
|
-
def
|
115
|
-
|
116
|
-
person.names.any? {|name| log_lines.last.line.match(name)}
|
117
|
-
end.map(&:display_name).join(', ')
|
44
|
+
def knowledge_debt
|
45
|
+
KnowledgeDebt.new(@log_lines, @card_prefix, @names).knowledge_debt
|
118
46
|
end
|
119
47
|
|
120
|
-
def
|
121
|
-
|
122
|
-
most_recent_commit_date(person1, person2).nil?
|
123
|
-
end.map do |person1, person2|
|
124
|
-
"#{person1}, #{person2}"
|
125
|
-
end
|
48
|
+
def pair_recency
|
49
|
+
PairRecency.new(@log_lines, @card_prefix, @names).pair_recency
|
126
50
|
end
|
127
51
|
end
|
128
52
|
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'pry'
|
2
|
+
module PairSee
|
3
|
+
class TooMuchStuff
|
4
|
+
require 'yamler'
|
5
|
+
require_relative 'pair_commit_count'
|
6
|
+
require_relative 'date_combo'
|
7
|
+
require_relative 'log_lines'
|
8
|
+
require_relative 'log_line_parse'
|
9
|
+
require_relative 'card'
|
10
|
+
require_relative 'cards_per_person'
|
11
|
+
require_relative 'active_devs'
|
12
|
+
|
13
|
+
def initialize(options)
|
14
|
+
@log_lines = LogLineParse.new(options[:repo_locations], options[:after_date]).log_lines
|
15
|
+
@active_devs = ActiveDevs.new(@log_lines, options[:names]).devs
|
16
|
+
|
17
|
+
cards_per_person = CardsPerPerson.new(@log_lines, options[:card_prefix], options[:names])
|
18
|
+
@devs = cards_per_person.people
|
19
|
+
@dev_pairs = cards_per_person.dev_pairs
|
20
|
+
|
21
|
+
@card_prefixes = options[:card_prefix]
|
22
|
+
end
|
23
|
+
|
24
|
+
def pretty_card_data
|
25
|
+
card_data(@card_prefixes).map do |card|
|
26
|
+
card&.pretty
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def pretty_card_data_by_commits
|
31
|
+
card_data(@card_prefixes).compact.sort_by.sort_by(&:number_of_commits).reverse.map(&:pretty)
|
32
|
+
end
|
33
|
+
|
34
|
+
def card_data(card_prefixes)
|
35
|
+
card_prefixes.map do |card_prefix|
|
36
|
+
card_numbers(card_prefix).map do |card_name|
|
37
|
+
Card.new(card_name, commits_on_card(card_name).sort_by(&:date))
|
38
|
+
end
|
39
|
+
end.flatten.sort_by(&:duration).reverse
|
40
|
+
end
|
41
|
+
|
42
|
+
def commits_on_card(card_name)
|
43
|
+
@log_lines.select { |line| line.contains_card_name?(card_name) }
|
44
|
+
end
|
45
|
+
|
46
|
+
def card_numbers(card_prefix)
|
47
|
+
@log_lines.select do |line|
|
48
|
+
line.contains_card?(card_prefix)
|
49
|
+
end.map do |line|
|
50
|
+
line.card_name([card_prefix])
|
51
|
+
end.uniq.compact
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_card_prefix(config_file)
|
55
|
+
config = YAML.load_file(config_file)
|
56
|
+
config['card_prefix']
|
57
|
+
end
|
58
|
+
|
59
|
+
def pair_commits
|
60
|
+
@dev_pairs.map do |person1, person2|
|
61
|
+
log_lines_commits_for_pair = @log_lines.commits_for_pair person1, person2
|
62
|
+
PairCommitCount.new(log_lines_commits_for_pair.count, person1, person2)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def solo_commits
|
67
|
+
@devs.map do |dev|
|
68
|
+
PairCommitCount.new(@log_lines.solo_commits(@devs, dev).count, dev)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def all_commits
|
73
|
+
pairs_result = Hash[@dev_pairs.map { |k, v| [names_key(k, v), 0] }]
|
74
|
+
solos_result = Hash[@devs.map { |k| [k.display_name, 0] }]
|
75
|
+
result = pairs_result.merge solos_result
|
76
|
+
|
77
|
+
@log_lines.each do |ll|
|
78
|
+
result = method_name(ll, result)
|
79
|
+
end
|
80
|
+
result
|
81
|
+
.sort_by { |_, count| count }
|
82
|
+
.reject { |_, count| count == 0 }
|
83
|
+
.map { |names, count| "#{names}: #{count}" }
|
84
|
+
end
|
85
|
+
|
86
|
+
def method_name(ll, result)
|
87
|
+
@dev_pairs.each do |d1, d2|
|
88
|
+
if ll.authored_by?(d1, d2)
|
89
|
+
result[names_key(d1, d2)] += 1
|
90
|
+
return result
|
91
|
+
elsif is_solo_by?(@devs, d1, ll)
|
92
|
+
result[d1.display_name] += 1
|
93
|
+
return result
|
94
|
+
elsif is_solo_by?(@devs, d2, ll)
|
95
|
+
result[d2.display_name] += 1
|
96
|
+
return result
|
97
|
+
end
|
98
|
+
end
|
99
|
+
result
|
100
|
+
end
|
101
|
+
|
102
|
+
def is_solo_by?(devs, person, log_line)
|
103
|
+
no_other_devs_in_commit = (devs - [person]).none? { |dx| log_line.authored_by?(dx) }
|
104
|
+
log_line.authored_by?(person) && no_other_devs_in_commit
|
105
|
+
end
|
106
|
+
|
107
|
+
def names_key(k, v)
|
108
|
+
[k, v].sort_by(&:display_name).map(&:to_s).join(', ')
|
109
|
+
end
|
110
|
+
|
111
|
+
def b(log_line, person1)
|
112
|
+
log_line.authored_by?(person1) && (people - [person1]).none? { |single_person| log_line.authored_by?(single_person) }
|
113
|
+
end
|
114
|
+
|
115
|
+
def a(log_line, person1, person2)
|
116
|
+
log_line.authored_by?(person1, person2)
|
117
|
+
end
|
118
|
+
|
119
|
+
def commits_for_pair(person1, person2)
|
120
|
+
@log_lines.commits_for_pair person1, person2
|
121
|
+
end
|
122
|
+
|
123
|
+
def commits_not_by_known_person
|
124
|
+
@log_lines.commits_not_by_known_person @devs
|
125
|
+
end
|
126
|
+
|
127
|
+
def most_recent_commit_date(person1, person2)
|
128
|
+
recent_commit = commits_for_pair(person1, person2).sort_by(&:date).first
|
129
|
+
recent_commit ? recent_commit.date : nil
|
130
|
+
end
|
131
|
+
|
132
|
+
def all_most_recent_commits
|
133
|
+
@dev_pairs.map do |person1, person2|
|
134
|
+
DateCombo.new(most_recent_commit_date(person1, person2), person1, person2)
|
135
|
+
end.sort.reverse.map &:to_s
|
136
|
+
end
|
137
|
+
|
138
|
+
def recommended_pairings
|
139
|
+
should_pair = unpaired_in_range
|
140
|
+
should_pair.empty? ? [least_recent_pair] : should_pair
|
141
|
+
end
|
142
|
+
|
143
|
+
def least_recent_pair
|
144
|
+
devs.select do |person|
|
145
|
+
person.names.any? { |name| @log_lines.last.line.match(name) }
|
146
|
+
end.map(&:display_name).join(', ')
|
147
|
+
end
|
148
|
+
|
149
|
+
def unpaired_in_range
|
150
|
+
@dev_pairs.select do |person1, person2|
|
151
|
+
most_recent_commit_date(person1, person2).nil?
|
152
|
+
end.map do |person1, person2|
|
153
|
+
"#{person1}, #{person2}"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|