commit-comment-tools 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +8 -0
- data/Gemfile +20 -0
- data/README.md +26 -0
- data/Rakefile +46 -0
- data/bin/git-stats +71 -0
- data/bin/report-analyzer +73 -0
- data/commit-comment-tools.gemspec +67 -0
- data/doc/text/gpl-3.0.txt +674 -0
- data/doc/text/news.md +5 -0
- data/doc/text/scenario.txt +168 -0
- data/lib/commit-comment-tools/entry.rb +45 -0
- data/lib/commit-comment-tools/generator.rb +4 -0
- data/lib/commit-comment-tools/generator/csv.rb +63 -0
- data/lib/commit-comment-tools/generator/graph.rb +25 -0
- data/lib/commit-comment-tools/report-normalizer.rb +58 -0
- data/lib/commit-comment-tools/report-parser.rb +98 -0
- data/lib/commit-comment-tools/repository-loader.rb +131 -0
- data/lib/commit-comment-tools/repository-stats.rb +113 -0
- data/lib/commit-comment-tools/version.rb +20 -0
- data/test/run-test.rb +32 -0
- data/test/test-entry.rb +78 -0
- data/test/test-report-normalizer.rb +87 -0
- data/test/test-report-parser.rb +111 -0
- metadata +230 -0
data/doc/text/news.md
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
# -*- org -*-
|
2
|
+
#+STARTUP: overview
|
3
|
+
#+STARTUP: hidestars
|
4
|
+
|
5
|
+
* 導入研修
|
6
|
+
|
7
|
+
研修でやることの説明をする。↓のリストを読んでやることの説明をする。全
|
8
|
+
体の流れを説明する。
|
9
|
+
|
10
|
+
- 「リーダブルコードの解説」を読む (10分)
|
11
|
+
http://www.clear-code.com/blog/2012/6/11.html
|
12
|
+
|
13
|
+
「リーダブルコードの解説」を読むことで須藤が考える「リーダブルコードを
|
14
|
+
書くために必要なこと」を知ってもらいます。
|
15
|
+
|
16
|
+
- 「リーダブルコードの解説」の解説 (5分)
|
17
|
+
|
18
|
+
「リーダブルコードの解説」を書いた時点と現在では、須藤の考え方も変わっ
|
19
|
+
ているため、考え方の変わった部分について説明します。
|
20
|
+
|
21
|
+
- 「Ruby コードの感想戦 【第 1 回】 WikiR」を読む (20分)
|
22
|
+
http://jp.rubyist.net/magazine/?0040-CodePostMortem
|
23
|
+
|
24
|
+
他の人がどんな読み方をするのか知っておくと、コードを読むときの視点が増
|
25
|
+
えるので、その一例として須藤の読み方を知ってもらいます。
|
26
|
+
|
27
|
+
- 「Ruby コードの感想戦 【第 1 回】 WikiR」の解説 (5分)
|
28
|
+
|
29
|
+
須藤がどういう読み方をしていたのか簡単に解説したあと、参加者のみなさん
|
30
|
+
に普段どのようにしてコードを読んでいるのか聞きます。
|
31
|
+
|
32
|
+
そのあと、講師の読み方を説明します。
|
33
|
+
|
34
|
+
- 実際にやってもらう (10分)
|
35
|
+
|
36
|
+
1人ずつ2,3分くらいで実際にコミットメールを読んでもらいます。
|
37
|
+
1人がやっている間、他の人はその人の周りに集ります。
|
38
|
+
|
39
|
+
- 感想を聞く (10分)
|
40
|
+
|
41
|
+
やってもらった感想を聞く。
|
42
|
+
|
43
|
+
- コメントの仕方 (5分)
|
44
|
+
|
45
|
+
どういう点に注意してコメントをするのか説明します。
|
46
|
+
|
47
|
+
- まとめ (5分)
|
48
|
+
|
49
|
+
** 「リーダブルコードの解説」を読む (10分)
|
50
|
+
|
51
|
+
「リーダブルコードの解説」を10分くらいで読んでください。
|
52
|
+
http://www.clear-code.com/blog/2012/6/11.html
|
53
|
+
|
54
|
+
「リーダブルコードの解説 ククログ」でぐぐると一番上に表示されます。
|
55
|
+
|
56
|
+
リーダブルコードの解説にはリーダブルなコードを継続的に書くために必要な
|
57
|
+
ことが書いてあります。また、リーダブルなコードを書くことを始めたばかり
|
58
|
+
の頃に困りそうなことも書いてあります。
|
59
|
+
|
60
|
+
|
61
|
+
(大きめの字で印刷して配ってもいいかも)
|
62
|
+
|
63
|
+
** 「リーダブルコードの解説」の解説 (5分)
|
64
|
+
|
65
|
+
「リーダブルコードの解説」には、まず自分がリーダブルなコードを書くんだ
|
66
|
+
というようなことが書かれていますが、普通の人はいきなりリーダブルないい
|
67
|
+
コードを書くことはできません。なぜなら、いいコードを読んだ経験がないか
|
68
|
+
らです。いいコードを読んだ経験がないと、いいコードを書くことは難しいの
|
69
|
+
で、まずはコードを読む習慣をつける必要があります。
|
70
|
+
|
71
|
+
いいコードは読みやすく、コミットメールに載っている差分だけ読んでも書い
|
72
|
+
た人の意図が理解できるものです。一方、よくないコードは、コミットメール
|
73
|
+
に載っている差分だけ読んでも、よくないコードであることがわかることが多
|
74
|
+
いです。なぜなら、よくないコードは何かしら「歪み」や「臭い」を持ってい
|
75
|
+
るからです。
|
76
|
+
|
77
|
+
コミットメールを読んで、読みやすいと思ったコミットやいい書き方をしてい
|
78
|
+
るなと思ったコミットは書き方を真似て、自分のコミットに取り入れてくださ
|
79
|
+
い。そのコミットに使われていた書き方を使うと、真似された方は真似されて
|
80
|
+
いることに気付きます。同じ書き方を使ったコミットが増えるとまわりの人も
|
81
|
+
気付いて真似するので、いいコードが広まるという流れになればいいと思って
|
82
|
+
います。
|
83
|
+
|
84
|
+
そして、コミットへのコメントサービスでは、コミットメールを読む習慣作り
|
85
|
+
の最初の一歩目をお手伝いします。
|
86
|
+
|
87
|
+
|
88
|
+
** 「Ruby コードの感想戦 【第 1 回】 WikiR」を読む (20分)
|
89
|
+
|
90
|
+
「Ruby コードの感想戦 【第 1 回】 WikiR」を10分くらいで読んでください。
|
91
|
+
http://jp.rubyist.net/magazine/?0040-CodePostMortem
|
92
|
+
|
93
|
+
他の人がどんな読み方をするのか知っておくことは重要です。なぜなら、コー
|
94
|
+
ドを読むときの視点が増えるからです。コードを読むときの視点が増えると、
|
95
|
+
視野が広くなり、自分がコードを書くときの引き出しが増えます。他の人のコー
|
96
|
+
ドの読み方の一例として須藤がコードを読むときにどんなことを考えながら読
|
97
|
+
んでいるかを知ってもらいます。
|
98
|
+
|
99
|
+
Rubyの機能やライブラリの説明が何ヶ所かありますが、その部分は「ふーん、
|
100
|
+
そうなのか」程度で流し読みしてもらって大丈夫です。
|
101
|
+
|
102
|
+
(大きめの字で印刷して配ってもいいかも)
|
103
|
+
|
104
|
+
** 「Ruby コードの感想戦 【第 1 回】 WikiR」の解説 (5分)
|
105
|
+
|
106
|
+
須藤の読み方は、書いた人の意図を想像しながら読むというものでした。しか
|
107
|
+
し、中にはあまり意図などなく書いている人もいます。
|
108
|
+
|
109
|
+
普段、どのようにしてコードやコミットメールを読んでいますか?
|
110
|
+
(順番に聞いていく)
|
111
|
+
(今後に活かすため、記録する)
|
112
|
+
|
113
|
+
講師のコミットメールの読み方を説明します。
|
114
|
+
|
115
|
+
- コミットログを読む
|
116
|
+
- コミットの内容とコミットログの内容が一致しているか確認する
|
117
|
+
- 一致していないときは注意して読む
|
118
|
+
- 一致しているときは、流し読みする
|
119
|
+
- あんまり難しいことは考えない
|
120
|
+
- 間違いを見つける意識では読まない
|
121
|
+
|
122
|
+
あと、自分にとって重要なプロジェクトかどうかで変わります。
|
123
|
+
|
124
|
+
** 実際にやってもらう (15分)
|
125
|
+
|
126
|
+
# 具体的な案はないが、毎回初見のコミットメールを用意するのは大変かも。
|
127
|
+
# 他の導入先のコードは初見のはずなので特に問題ないか
|
128
|
+
|
129
|
+
対象プロジェクトのコミットのうちそのときの最新10から20コミットくらいでやる。
|
130
|
+
|
131
|
+
- 自分がやる(3分)
|
132
|
+
- 1人3分でやってもらう(10分)
|
133
|
+
|
134
|
+
もっと長い時間やったときは記録も付けてもらう
|
135
|
+
|
136
|
+
- 記録を付けてもらう(2分)
|
137
|
+
- 読んだ割合(ざっくり)、印象に残ったコミット
|
138
|
+
|
139
|
+
** 感想を聞く (10分)
|
140
|
+
|
141
|
+
それぞれの人に感想を聞く。
|
142
|
+
|
143
|
+
- 読んでみてどうだった?
|
144
|
+
- 気になったことは?
|
145
|
+
|
146
|
+
(感想など聞いた話は次に活かすために記録する)
|
147
|
+
|
148
|
+
** コメントする方法を説明する (5分)
|
149
|
+
|
150
|
+
- 場所。気になったのはどこかを書く。
|
151
|
+
- 理由。なぜ気になったのか。○○だから読みにくい。理由がなければ無いこ
|
152
|
+
とを書く。
|
153
|
+
- 改善案。改善案があるかないか。改善案があればそれを書く、改善案がなけ
|
154
|
+
れば無いことを書く。
|
155
|
+
|
156
|
+
** まとめ (5分)
|
157
|
+
|
158
|
+
例えば、コミットメールを読むのに使う時間は一日30分までと決めると、時間
|
159
|
+
を使い過ぎることはなくなるので、試してほしいです。徐々にコミットされる
|
160
|
+
コードが読みやすくなってくれば、読めるコミットメールの数や割合が増えて
|
161
|
+
くると思います。
|
162
|
+
|
163
|
+
質問はありますか?
|
164
|
+
|
165
|
+
他に気になることはないですか?
|
166
|
+
|
167
|
+
(何度か質問を繰り返して、疑問点を出してもらってできるかぎり解消しておく。)
|
168
|
+
(また、出てきた質問と回答はメモを取っておいて、次回以降に活かす。)
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright (C) 2013 Haruka Yoshihara <yoshihara@clear-code.com>
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
require "date"
|
19
|
+
|
20
|
+
module CommitCommentTools
|
21
|
+
class Entry
|
22
|
+
class InvalidEntryError < StandardError
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :name, :date, :read_ratio, :comment
|
26
|
+
|
27
|
+
def initialize(name, entry_chunk)
|
28
|
+
@name = name
|
29
|
+
@date = nil
|
30
|
+
@read_ratio = nil
|
31
|
+
@comment = nil
|
32
|
+
|
33
|
+
if /\A(\d\d\d\d-\d+-\d+):(\d+)%:(.*)\z/m =~ entry_chunk
|
34
|
+
@date = Date.parse($1).strftime("%Y-%m-%d")
|
35
|
+
@read_ratio = $2.to_i
|
36
|
+
@comment = $3
|
37
|
+
else
|
38
|
+
valid_format = "DATE:READ_RATIO%:COMMENT"
|
39
|
+
error_message = "The expected format of entry like below:\n" +
|
40
|
+
"\"#{valid_format}\", but was \"#{entry_chunk}\"."
|
41
|
+
raise(InvalidEntryError, error_message)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright (C) 2013 Kenji Okimoto <okimoto@clear-code.com>
|
4
|
+
# Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
|
5
|
+
#
|
6
|
+
# This program is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# This program is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
|
19
|
+
require "csv"
|
20
|
+
|
21
|
+
module CommitCommentTools
|
22
|
+
module Generator
|
23
|
+
class CSV
|
24
|
+
def initialize(reports, options={})
|
25
|
+
@reports = reports
|
26
|
+
@options = options
|
27
|
+
end
|
28
|
+
|
29
|
+
def generate
|
30
|
+
members = []
|
31
|
+
daily_read_ratios = {}
|
32
|
+
@reports.each do |name, diaries|
|
33
|
+
members << name
|
34
|
+
diaries.each do |date, report|
|
35
|
+
daily_read_ratios[date] ||= {}
|
36
|
+
daily_read_ratios[date][name] = report[:read_ratio]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
sorted_members = members.sort
|
40
|
+
csv_string = generate_csv(sorted_members, daily_read_ratios)
|
41
|
+
# TODO write to file
|
42
|
+
puts csv_string
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
def generate_csv(members, daily_read_ratios)
|
47
|
+
::CSV.generate do |csv|
|
48
|
+
csv << ["DATE", *members]
|
49
|
+
daily_read_ratios.sort_by {|date, _| date}.each do |date, read_ratios|
|
50
|
+
row_values = daily_record2row(read_ratios, members)
|
51
|
+
csv << [date, *row_values]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def daily_record2row(read_ratios, members)
|
57
|
+
members.collect do |name|
|
58
|
+
read_ratios[name] || 0
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright (C) 2013 Haruka Yoshihara <yoshihara@clear-code.com>
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
require "gruff"
|
19
|
+
|
20
|
+
module CommitCommentTools
|
21
|
+
module Generator
|
22
|
+
class Graph
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright (C) 2013 Haruka Yoshihara <yoshihara@clear-code.com>
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
require "date"
|
19
|
+
|
20
|
+
module CommitCommentTools
|
21
|
+
class ReportNormlizer
|
22
|
+
class << self
|
23
|
+
def normalize(parsed_reports)
|
24
|
+
new.normalize(parsed_reports)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
@person_reports = {}
|
30
|
+
end
|
31
|
+
|
32
|
+
def normalize(parsed_reports)
|
33
|
+
parsed_reports.each do |person, daily_report|
|
34
|
+
normalize_daily_report(person, daily_report)
|
35
|
+
end
|
36
|
+
@person_reports
|
37
|
+
end
|
38
|
+
|
39
|
+
def normalize_daily_report(person, daily_report)
|
40
|
+
@person_reports[person] = {}
|
41
|
+
|
42
|
+
daily_report.each do |date, report|
|
43
|
+
normalized_date = normalize_date(date)
|
44
|
+
@person_reports[person][normalized_date] = normalize_report(report)
|
45
|
+
end
|
46
|
+
@person_reports
|
47
|
+
end
|
48
|
+
|
49
|
+
def normalize_date(date)
|
50
|
+
Date.parse(date).strftime("%Y-%m-%d")
|
51
|
+
end
|
52
|
+
|
53
|
+
def normalize_report(report)
|
54
|
+
report[:read_ratio] = report[:read_ratio].to_i
|
55
|
+
report
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright (C) 2013 Haruka Yoshihara <yoshihara@clear-code.com>
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
require "English"
|
19
|
+
|
20
|
+
module CommitCommentTools
|
21
|
+
class ReportParser
|
22
|
+
class << self
|
23
|
+
def parse(report_directory=nil)
|
24
|
+
report_directory ||= "."
|
25
|
+
report_unexpanded_path = File.join(report_directory, "**", "*.txt")
|
26
|
+
report_file_paths = Dir.glob(report_unexpanded_path)
|
27
|
+
|
28
|
+
new.parse(report_file_paths)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
@person_reports = {}
|
34
|
+
end
|
35
|
+
|
36
|
+
def parse(report_files)
|
37
|
+
report_files.each do |report_file|
|
38
|
+
person_name = File.basename(report_file, ".txt")
|
39
|
+
next unless person_name == person_name.downcase
|
40
|
+
daily_entries = parse_file(report_file)
|
41
|
+
@person_reports[person_name] = generate_daily_report(daily_entries)
|
42
|
+
end
|
43
|
+
|
44
|
+
@person_reports
|
45
|
+
end
|
46
|
+
|
47
|
+
def parse_file(report_file)
|
48
|
+
File.open(report_file, "r") do |report_io|
|
49
|
+
parse_stream(report_io)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def parse_stream(report_io)
|
54
|
+
entries = []
|
55
|
+
date = ""
|
56
|
+
read_ratio = ""
|
57
|
+
comment = ""
|
58
|
+
|
59
|
+
report_io.each_line.with_index do |line, line_number|
|
60
|
+
case line.chomp
|
61
|
+
when /\A(\d\d\d\d-\d+-\d+):(\d+)%:?(.*)\z/
|
62
|
+
unless line_number.zero?
|
63
|
+
entries << entry(date, read_ratio, comment)
|
64
|
+
end
|
65
|
+
|
66
|
+
date = $1
|
67
|
+
read_ratio = $2
|
68
|
+
comment = $3
|
69
|
+
when /\A\s+/
|
70
|
+
comment << $POSTMATCH << "\n"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
unless comment.empty?
|
75
|
+
entries << entry(date, read_ratio, comment)
|
76
|
+
end
|
77
|
+
entries
|
78
|
+
end
|
79
|
+
|
80
|
+
def entry(date, read_ratio, comment)
|
81
|
+
{
|
82
|
+
:date => date,
|
83
|
+
:read_ratio => read_ratio,
|
84
|
+
:comment => comment.chomp
|
85
|
+
}
|
86
|
+
end
|
87
|
+
|
88
|
+
def generate_daily_report(entries)
|
89
|
+
daily_report = {}
|
90
|
+
|
91
|
+
entries.each do |entry|
|
92
|
+
date = entry.delete(:date)
|
93
|
+
daily_report[date] = entry
|
94
|
+
end
|
95
|
+
daily_report
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|