codespicuous 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +7 -0
- data/LICENSE +29 -0
- data/README.md +2 -0
- data/Rakefile +6 -0
- data/bin/codespicuous +4 -0
- data/bin/filezilla/codespicuous.yaml +23 -0
- data/bin/filezilla/committers.csv +4 -0
- data/bin/filezilla/svnlog/filezilla.log +3939 -0
- data/bin/filezilla/svnlog/python.log +3 -0
- data/bin/filezilla/svnlog/xiph.log +265 -0
- data/codespicuous.gemspec +22 -0
- data/lib/codespicuous.rb +38 -0
- data/lib/codespicuous/codespicuous.rb +55 -0
- data/lib/codespicuous/codespicuous_config.rb +35 -0
- data/lib/codespicuous/codespicuousconfigurator.rb +136 -0
- data/lib/codespicuous/commandrunner.rb +13 -0
- data/lib/codespicuous/commithistory.rb +71 -0
- data/lib/codespicuous/commithistory_builder.rb +49 -0
- data/lib/codespicuous/commits.rb +147 -0
- data/lib/codespicuous/commitstatistics.rb +245 -0
- data/lib/codespicuous/committer.rb +105 -0
- data/lib/codespicuous/danielparser.rb +31 -0
- data/lib/codespicuous/dateutil.rb +18 -0
- data/lib/codespicuous/metrics_generator.rb +22 -0
- data/lib/codespicuous/metrics_generator_csv.rb +67 -0
- data/lib/codespicuous/metrics_generator_daniel.rb +13 -0
- data/lib/codespicuous/participantsparser_from_csv.rb +37 -0
- data/lib/codespicuous/repositories.rb +80 -0
- data/lib/codespicuous/repository_lister.rb +8 -0
- data/lib/codespicuous/svn_client.rb +14 -0
- data/lib/codespicuous/svn_data_collector.rb +50 -0
- data/lib/codespicuous/svn_log_parser.rb +100 -0
- data/lib/codespicuous/teams.rb +99 -0
- data/lib/codespicuous/version.rb +4 -0
- data/spec/codespicuous_spec.rb +81 -0
- data/spec/codespicuousconfigurator_spec.rb +202 -0
- data/spec/commithistories_data.rb +46 -0
- data/spec/commithistory_spec.rb +57 -0
- data/spec/commits_spec.rb +93 -0
- data/spec/committers_spec.rb +66 -0
- data/spec/danielparser_spec.rb +12 -0
- data/spec/integration_filezilla_spec.rb +41 -0
- data/spec/metrics_generator_csv_spec.rb +91 -0
- data/spec/metrics_generator_daniel_spec.rb +10 -0
- data/spec/metrics_generator_spec.rb +35 -0
- data/spec/repositories_spec.rb +29 -0
- data/spec/svn_client_spec.rb +16 -0
- data/spec/svn_data_collector_spec.rb +93 -0
- data/spec/svn_log_parser_spec.rb +141 -0
- data/spec/teams_spec.rb +16 -0
- metadata +142 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
class CommitHistory
|
4
|
+
|
5
|
+
attr_reader :commits, :teams, :repositories, :committers
|
6
|
+
|
7
|
+
def initialize(commits = Commits.new)
|
8
|
+
@commits = Commits.new
|
9
|
+
@committers = Committers.new
|
10
|
+
@teams = Teams.new
|
11
|
+
@repositories = Repositories.new
|
12
|
+
add_commits(commits)
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_commit(commit)
|
16
|
+
@commits.add(commit)
|
17
|
+
committer(commit.author).add_commit(commit)
|
18
|
+
@repositories.add(commit.repository)
|
19
|
+
commit.repository.add_commit(commit)
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_commits(commits)
|
23
|
+
commits.each { |commit|
|
24
|
+
add_commit(commit)
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_team_member(team, member)
|
29
|
+
team = @teams.team(team)
|
30
|
+
team.add_member(committer(member))
|
31
|
+
end
|
32
|
+
|
33
|
+
def committer(name)
|
34
|
+
@committers.committer(name)
|
35
|
+
end
|
36
|
+
|
37
|
+
def repository(name)
|
38
|
+
@repositories.repository(name)
|
39
|
+
end
|
40
|
+
|
41
|
+
def team(name)
|
42
|
+
@teams.team(name)
|
43
|
+
end
|
44
|
+
|
45
|
+
def repository_names
|
46
|
+
@repositories.repository_names
|
47
|
+
end
|
48
|
+
|
49
|
+
def amount_of_comitters
|
50
|
+
@committers.amount
|
51
|
+
end
|
52
|
+
|
53
|
+
def amount_of_commits_for_team_in_week(team_name, week)
|
54
|
+
@commits.inject(0) { |amount_of_commits, commit|
|
55
|
+
amount_of_commits + ((commit.by_team_with_name?(team_name) && commit.in_week?(week)) ? 1 : 0)
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
def earliest_commit_date
|
60
|
+
@commits.earliest_commit_date
|
61
|
+
end
|
62
|
+
|
63
|
+
def latest_commit_date
|
64
|
+
@commits.latest_commit_date
|
65
|
+
end
|
66
|
+
|
67
|
+
def == commit_history
|
68
|
+
@commits == commit_history.commits
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
class CommitHistoryBuilder
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@commit_history = CommitHistory.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def build
|
9
|
+
@commit_history
|
10
|
+
end
|
11
|
+
|
12
|
+
def in_repository(name)
|
13
|
+
@current_repository = Repository.new(name, "")
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def commits_of(name)
|
18
|
+
@author = name
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def of_team(name)
|
23
|
+
@team = name
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def at(date)
|
28
|
+
@commit_date = date
|
29
|
+
add_commit_to_history
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def times(number)
|
34
|
+
(number-1).times {
|
35
|
+
add_commit_to_history
|
36
|
+
}
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
def add_commit_to_history
|
41
|
+
commit = Commit.new
|
42
|
+
commit.author = @author
|
43
|
+
commit.date = DateTime.parse(@commit_date)
|
44
|
+
commit.repository = @current_repository
|
45
|
+
@commit_history.add_commit(commit)
|
46
|
+
@commit_history.add_team_member(@team, @author)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
@@ -0,0 +1,147 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
class Change
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@changed_property = false
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_accessor :type, :file, :copyfrom, :copyrev, :kind
|
10
|
+
|
11
|
+
def changed_property?
|
12
|
+
@changed_property
|
13
|
+
end
|
14
|
+
|
15
|
+
def property_changed
|
16
|
+
@changed_property = true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class CommitSameButDifferentError < Exception
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
class Commit
|
25
|
+
|
26
|
+
def initialize
|
27
|
+
@changes = []
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_accessor :author, :revision, :message, :date, :changes, :repository, :committer
|
31
|
+
|
32
|
+
def by_team_with_name?(team_name)
|
33
|
+
committer.in_team_with_name?(team_name)
|
34
|
+
end
|
35
|
+
|
36
|
+
def in_week?(date)
|
37
|
+
@date.cwyear == date.cwyear && @date.cweek == date.cweek
|
38
|
+
end
|
39
|
+
|
40
|
+
def my_object_id
|
41
|
+
object_id
|
42
|
+
end
|
43
|
+
|
44
|
+
def inspect
|
45
|
+
"Commit(o:#{my_object_id}) #{repository.name}:#{revision}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def ==(commit)
|
49
|
+
is_equal = @repository == commit.repository && @revision == commit.revision
|
50
|
+
|
51
|
+
raise CommitSameButDifferentError.new if is_equal && @author != commit.author
|
52
|
+
is_equal
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
class Commits
|
58
|
+
|
59
|
+
attr_reader :commits
|
60
|
+
|
61
|
+
def initialize(commits = [])
|
62
|
+
@commits = commits
|
63
|
+
end
|
64
|
+
|
65
|
+
def [] index
|
66
|
+
@commits[index]
|
67
|
+
end
|
68
|
+
|
69
|
+
def each
|
70
|
+
@commits.each { |commit|
|
71
|
+
yield commit
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
def inject(value, &block)
|
76
|
+
@commits.inject(value, &block)
|
77
|
+
end
|
78
|
+
|
79
|
+
def commits_in_repository(name)
|
80
|
+
@commits.select { |commit| commit.repository.name == name }
|
81
|
+
end
|
82
|
+
|
83
|
+
def add commit
|
84
|
+
@commits << commit
|
85
|
+
end
|
86
|
+
|
87
|
+
def add_commits commits
|
88
|
+
commits.each { |commit|
|
89
|
+
add commit
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
def set_repository(repository)
|
94
|
+
each { |commit|
|
95
|
+
commit.repository = repository
|
96
|
+
}
|
97
|
+
end
|
98
|
+
|
99
|
+
def find_commit(repository, revision)
|
100
|
+
@commits.find { |commit| commit.repository == repository && commit.revision == revision}
|
101
|
+
end
|
102
|
+
|
103
|
+
def find_by_committer name
|
104
|
+
Commits.new (@commits.select { |commit| commit.author == name })
|
105
|
+
end
|
106
|
+
|
107
|
+
def earliest_commit_date
|
108
|
+
@commits.inject(DateTime.now) { |date, commit| date < commit.date ? date : commit.date }
|
109
|
+
end
|
110
|
+
|
111
|
+
def latest_commit_date
|
112
|
+
@commits.inject(DateTime.new(1977)) { |date, commit| date > commit.date ? date : commit.date }
|
113
|
+
end
|
114
|
+
|
115
|
+
def amount
|
116
|
+
@commits.size
|
117
|
+
end
|
118
|
+
|
119
|
+
def amount_of_commits_to_repository(name)
|
120
|
+
commits_in_repository(name).size
|
121
|
+
end
|
122
|
+
|
123
|
+
def amount_of_weeks_committed_in_repository(name)
|
124
|
+
commits_in_repository(name).collect { |commit| [commit.date.cwyear, commit.date.cweek]}.uniq.size
|
125
|
+
end
|
126
|
+
|
127
|
+
def amount_of_commits_in_week(week_start)
|
128
|
+
@commits.select { |commit| commit.in_week?(week_start)}.size
|
129
|
+
end
|
130
|
+
|
131
|
+
def amount_of_commits_to_repository_in_week(name, week_start)
|
132
|
+
commits_in_repository(name).select { |commit|
|
133
|
+
commit.in_week?(week_start)
|
134
|
+
}.size
|
135
|
+
end
|
136
|
+
|
137
|
+
def == commits
|
138
|
+
@commits == commits.commits
|
139
|
+
end
|
140
|
+
|
141
|
+
def +(commits)
|
142
|
+
result = Commits.new
|
143
|
+
result.add_commits(self)
|
144
|
+
result.add_commits(commits)
|
145
|
+
result
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,245 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'csv'
|
3
|
+
|
4
|
+
class CommitStatisticsForCommitterInRepository
|
5
|
+
attr_writer :commits
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
self.commits = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def commit(date, amount)
|
12
|
+
@commits[DateTime.parse(date.to_s)] ||= 0
|
13
|
+
@commits[DateTime.parse(date.to_s)] += amount.to_i
|
14
|
+
end
|
15
|
+
|
16
|
+
def amount_of_commits
|
17
|
+
@commits.values.inject(0) { |sum, commits_of_week| sum += commits_of_week }
|
18
|
+
end
|
19
|
+
|
20
|
+
def amount_of_weeks_committed
|
21
|
+
@commits.size
|
22
|
+
end
|
23
|
+
|
24
|
+
def amount_of_commits_in_week week_start
|
25
|
+
@commits[week_start] ? @commits[week_start] : 0
|
26
|
+
end
|
27
|
+
|
28
|
+
def first_week_committed
|
29
|
+
commit_week = DateTime.now
|
30
|
+
@commits.each_key { |date|
|
31
|
+
commit_week = date if date < commit_week
|
32
|
+
}
|
33
|
+
commit_week
|
34
|
+
end
|
35
|
+
|
36
|
+
def last_week_committed
|
37
|
+
commit_week = DateTime.new(1977)
|
38
|
+
@commits.each_key { |date|
|
39
|
+
commit_week = date if date > commit_week
|
40
|
+
}
|
41
|
+
commit_week
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class CommitStatisticsForCommitter
|
46
|
+
|
47
|
+
attr_accessor :username, :team, :commits_in_repositories
|
48
|
+
|
49
|
+
def initialize(username)
|
50
|
+
self.username = username
|
51
|
+
self.commits_in_repositories = {}
|
52
|
+
end
|
53
|
+
|
54
|
+
def commit(repository, date, amount)
|
55
|
+
repository(repository.name).commit(date, amount)
|
56
|
+
end
|
57
|
+
|
58
|
+
def repository name
|
59
|
+
@commits_in_repositories[name] ||= CommitStatisticsForCommitterInRepository.new
|
60
|
+
end
|
61
|
+
|
62
|
+
def repositories_committed_to
|
63
|
+
@commits_in_repositories.keys
|
64
|
+
end
|
65
|
+
|
66
|
+
def amount_of_commits
|
67
|
+
@commits_in_repositories.values.inject(0) { |sum, repository|
|
68
|
+
sum + repository.amount_of_commits
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
def amount_of_weeks_committed_to_repository name
|
73
|
+
repository(name).amount_of_weeks_committed
|
74
|
+
end
|
75
|
+
|
76
|
+
def amount_of_comnmits_to_repository name
|
77
|
+
repository(name).amount_of_commits
|
78
|
+
end
|
79
|
+
|
80
|
+
def amount_of_commits_in_week week_start
|
81
|
+
@commits_in_repositories.each_value.inject(0) { |sum, commits|
|
82
|
+
sum + commits.amount_of_commits_in_week(week_start)
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
def amount_of_commits_to_repository_in_week(name, week_start)
|
87
|
+
repository(name).amount_of_commits_in_week(week_start)
|
88
|
+
end
|
89
|
+
|
90
|
+
def first_week_committed
|
91
|
+
commit_week = DateTime.now
|
92
|
+
@commits_in_repositories.each_value { |commits|
|
93
|
+
commit_week = commits.first_week_committed if commits.first_week_committed < commit_week
|
94
|
+
}
|
95
|
+
commit_week
|
96
|
+
end
|
97
|
+
|
98
|
+
def last_week_committed
|
99
|
+
commit_week = DateTime.new(1977)
|
100
|
+
@commits_in_repositories.each_value { |commits|
|
101
|
+
commit_week = commits.last_week_committed if commits.last_week_committed > commit_week
|
102
|
+
}
|
103
|
+
commit_week
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class CommitStatistics
|
108
|
+
|
109
|
+
attr_accessor :committer_statistics
|
110
|
+
|
111
|
+
def initialize
|
112
|
+
self.committer_statistics = {}
|
113
|
+
end
|
114
|
+
|
115
|
+
def commits= commits
|
116
|
+
commits.each { |commit|
|
117
|
+
commit(commit.author, commit.repository, commit.date)
|
118
|
+
}
|
119
|
+
end
|
120
|
+
|
121
|
+
def teams= teams
|
122
|
+
teams.each_member { |team, member|
|
123
|
+
committer(member.username).team = team.name
|
124
|
+
}
|
125
|
+
end
|
126
|
+
|
127
|
+
def commit(username, repository, date)
|
128
|
+
committer(username).commit(repository, date, 1)
|
129
|
+
end
|
130
|
+
|
131
|
+
def committer username
|
132
|
+
@committer_statistics[username] ||= CommitStatisticsForCommitter.new(username)
|
133
|
+
end
|
134
|
+
|
135
|
+
def committer_in_team(team)
|
136
|
+
team_members = []
|
137
|
+
@committer_statistics.each_value { |committer|
|
138
|
+
team_members << committer.username if committer.team == team || team == nil
|
139
|
+
}
|
140
|
+
team_members
|
141
|
+
end
|
142
|
+
|
143
|
+
def repositories_committed_to
|
144
|
+
names = []
|
145
|
+
@committer_statistics.each_value { |stats_for_committer|
|
146
|
+
names << stats_for_committer.repositories_committed_to
|
147
|
+
}
|
148
|
+
names.flatten.uniq
|
149
|
+
end
|
150
|
+
|
151
|
+
def teams
|
152
|
+
teams = []
|
153
|
+
@committer_statistics.each_value { |stats_for_committer|
|
154
|
+
teams << stats_for_committer.team
|
155
|
+
}
|
156
|
+
teams.flatten.uniq.sort
|
157
|
+
end
|
158
|
+
|
159
|
+
def first_week_committed
|
160
|
+
commit_week = DateTime.now
|
161
|
+
@committer_statistics.each_value { |committer|
|
162
|
+
commit_week = committer.first_week_committed if committer.first_week_committed < commit_week
|
163
|
+
}
|
164
|
+
commit_week
|
165
|
+
end
|
166
|
+
|
167
|
+
def last_week_committed
|
168
|
+
commit_week = DateTime.new(1977)
|
169
|
+
@committer_statistics.each_value { |committer|
|
170
|
+
commit_week = committer.last_week_committed if committer.last_week_committed > commit_week
|
171
|
+
}
|
172
|
+
commit_week
|
173
|
+
end
|
174
|
+
|
175
|
+
def amount_of_comitters
|
176
|
+
self.committer_statistics.size
|
177
|
+
end
|
178
|
+
|
179
|
+
def amount_of_commits_for_team_in_week(team, week)
|
180
|
+
@committer_statistics.each_value.inject(0) { |amount_of_commits, committer|
|
181
|
+
amount_of_commits + ((committer.team == team) ? committer.amount_of_commits_in_week(week) : 0)
|
182
|
+
}
|
183
|
+
end
|
184
|
+
|
185
|
+
def amount_of_commits_to_repository_in_week(repository, week)
|
186
|
+
@committer_statistics.each_value.inject(0) { |amount_of_commits, committer|
|
187
|
+
amount_of_commits + committer.amount_of_commits_to_repository_in_week(repository, week)
|
188
|
+
}
|
189
|
+
end
|
190
|
+
|
191
|
+
def for_each_week
|
192
|
+
(first_week_committed..last_week_committed).step(7) { |week|
|
193
|
+
yield week
|
194
|
+
}
|
195
|
+
end
|
196
|
+
|
197
|
+
def string_date(date)
|
198
|
+
date.strftime("%Y-%m-%d")
|
199
|
+
end
|
200
|
+
|
201
|
+
def create_commit_table_row_for_committer_with_repository_info committer
|
202
|
+
[committer.username, committer.team, repositories_committed_to.map { |repository| committer.amount_of_comnmits_to_repository(repository)}, committer.amount_of_commits].flatten
|
203
|
+
end
|
204
|
+
|
205
|
+
def create_commit_table_rows_with_committers_and_repository_info(team_to_select)
|
206
|
+
@committer_statistics.values.select { |committer| committer.team == team_to_select }.map { |committer| create_commit_table_row_for_committer_with_repository_info(committer) }
|
207
|
+
end
|
208
|
+
|
209
|
+
def create_commit_table_with_committers_and_repository_info
|
210
|
+
CSV.generate do |csv|
|
211
|
+
csv << ["Committer", "Team", repositories_committed_to, "Total"].flatten
|
212
|
+
teams.each { |team|
|
213
|
+
create_commit_table_rows_with_committers_and_repository_info(team).each { |row| csv << row }
|
214
|
+
}
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def create_commit_table_with_weeks_and_team_commits
|
219
|
+
CSV.generate do |csv|
|
220
|
+
csv << ["Week", teams].flatten
|
221
|
+
for_each_week { |week|
|
222
|
+
csv << [string_date(week), teams.map { |team| amount_of_commits_for_team_in_week(team, week) } ].flatten
|
223
|
+
}
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def create_commit_table_with_week_and_repository_info
|
228
|
+
CSV.generate do |csv|
|
229
|
+
csv << ["Week", repositories_committed_to].flatten
|
230
|
+
for_each_week { |week|
|
231
|
+
csv << [string_date(week), repositories_committed_to.map { |repository| amount_of_commits_to_repository_in_week(repository, week) } ].flatten
|
232
|
+
}
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def create_commit_table_with_weeks_and_committers(team=nil)
|
237
|
+
CSV.generate do |csv|
|
238
|
+
csv << ["Week", committer_in_team(team) ].flatten
|
239
|
+
for_each_week { |week|
|
240
|
+
csv << [string_date(week), @committer_statistics.values.select { |committer| committer.team == team || team == nil }.map { |committer| committer.amount_of_commits_in_week(week)} ].flatten
|
241
|
+
}
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|