codespicuous 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0c9e7658c0084a439e6c7a6762410a263eafef15
4
- data.tar.gz: 2153cbf4df876dc4ddf7f697b6f67b9f396517ce
3
+ metadata.gz: 2f6aa844f077caec750d39a33e9c748daca60eed
4
+ data.tar.gz: 66f2b73f5bfe77d9bee7f12c20fbf0916eb46138
5
5
  SHA512:
6
- metadata.gz: 29678e91eb3a64c31c28fd764eb8c4c27a6dfd4ab3cbf3a2697255671e4823bc3ce13e7c9615fadedb546f8e655593eca3ff961f130a6a9f7f659a6e84e70bb0
7
- data.tar.gz: 01c4e1d04c671d7059f300339a264400525da87d51fbd9932e3f07d9db398cbda80495ea316e17d430ea6236a04b28260d44c5c8df5bc3f7a555b987d997e902
6
+ metadata.gz: 6fb02298619c7efe10bb65731cf6023d92ed9e7e2fd59042e01f9f90a8f1cfc4a330898569565badf7ecab0c05293b04b7c34b83696d66e6d2b6b7b8a63fae01
7
+ data.tar.gz: f880b34a43da171ee189fd8ba3e3d6ad66c6c466702902e23ecd2df0f1c505fc4fbff2629996e3cd19c9417d3278885b49aa59e7db0c1c9d330d9df40aef7262
@@ -6,6 +6,7 @@ Gem::Specification.new do |gem|
6
6
  gem.version = Codespicuous::VERSION
7
7
  gem.date = Date.today.to_s
8
8
  gem.license = "MIT"
9
+ gem.executables = [ "codespicuous" ]
9
10
 
10
11
  gem.summary = "Codespicuous is a tool for generating team based metrics from code"
11
12
  gem.description = "Codespicuous is a tool for generating several different metrics from codebases to gain insight in how the teams are working."
@@ -7,6 +7,7 @@ class Codespicuous
7
7
 
8
8
  def initialize
9
9
  @config = CodespicuousConfig.new
10
+ @commit_history = CommitHistory.new
10
11
  end
11
12
 
12
13
  def run(argv)
@@ -31,16 +32,14 @@ class Codespicuous
31
32
  configurator = CodespicuousConfigurator.new(@config)
32
33
  return false unless configurator.configure(argv)
33
34
 
34
- @repositories = configurator.repositories
35
- @committers = configurator.committers
36
- @teams = configurator.teams
35
+ @commit_history.configure(configurator.teams, configurator.repositories)
37
36
 
38
37
  true
39
38
  end
40
39
 
41
40
  def collect
42
- collector = SVNDataCollector.new(config)
43
- @commit_history = collector.collect_commit_history(repositories)
41
+ collector = SVNDataCollector.new(config, @commit_history)
42
+ collector.collect_commit_history(@commit_history.repositories)
44
43
  end
45
44
 
46
45
  def generate_output
@@ -3,7 +3,7 @@ require 'yaml'
3
3
  class CodespicuousConfigurator
4
4
 
5
5
 
6
- attr_reader :repositories, :repositories_to_check, :committers, :teams, :config
6
+ attr_reader :repositories, :repositories_to_check, :teams, :config
7
7
 
8
8
  def initialize(config)
9
9
 
@@ -12,7 +12,6 @@ class CodespicuousConfigurator
12
12
  @repositories = Repositories.new
13
13
  @repositories_to_check = Repositories.new
14
14
 
15
- @committers = Committers.new
16
15
  @teams = Teams.new
17
16
  end
18
17
 
@@ -63,7 +62,7 @@ class CodespicuousConfigurator
63
62
  puts "** Configuring options with \"#{config.path_to_configuration_file}\""
64
63
  yaml_content = YAML::load(File.read(config.path_to_configuration_file))
65
64
  config.offline = yaml_content["offline"] if yaml_content["offline"]
66
- #{@filezilla_path#{@filezilla_path}}yaml_content
65
+ yaml_content
67
66
  end
68
67
 
69
68
  def postprocess_yaml_configuration_repositories(yaml_content)
@@ -102,35 +101,37 @@ class CodespicuousConfigurator
102
101
  end
103
102
 
104
103
  def postprocess_yaml_configuration_committers(yaml_content)
105
- teams = yaml_content["teams"] || []
104
+ teams_yaml = yaml_content["teams"] || []
106
105
 
107
- teams.each { |team_name, team_members|
108
- new_team = Team.new(team_name)
106
+ teams_yaml.each do |team_name, team_members|
107
+
108
+ committers = Committers.new
109
109
  team_members.each { |person|
110
- committer = Committer.create_committer(person["Login"], person["First Name"], person["Last Name"], person["Email"], new_team)
111
- new_team.add_member(committer)
112
- @committers.add(committer)
113
- @teams.add(new_team)
110
+ committers.add(Committer.create_committer(person["Login"], person["First Name"], person["Last Name"], person["Email"]))
114
111
  }
115
- }
112
+
113
+ unless committers.empty?
114
+ new_team = Team.new(team_name)
115
+ new_team.add_members(committers)
116
+ @teams.add(new_team)
117
+ end
118
+ end
116
119
  end
117
120
 
118
121
  def find_alternative_configuration_files_for_committers
119
- return unless committers.empty?
122
+ return unless teams.empty?
120
123
  return unless File.exist?("committers.csv")
121
124
 
122
125
  puts '** Configuring committers with "committers.csv"'
123
126
 
124
- @committers = Committers.new
125
127
  @teams = Teams.new
126
128
 
127
129
  CSV.parse(File.read("committers.csv"), headers: true) { |row|
128
- team = @teams.team(row["Team"])
129
- committer = Committer.create_committer(row["Login"], row["First Name"], row["Last Name"], row["Email"], team)
130
+ committer = Committer.create_committer(row["Login"], row["First Name"], row["Last Name"], row["Email"])
131
+
132
+ team = @teams.team(row["Team"] || "")
130
133
  team.add_member(committer)
131
- @committers.add(committer)
132
134
  }
133
- @committers
134
135
  end
135
136
 
136
137
  end
@@ -4,12 +4,17 @@ class CommitHistory
4
4
 
5
5
  attr_reader :commits, :teams, :repositories, :committers
6
6
 
7
- def initialize(commits = Commits.new)
7
+ def initialize
8
8
  @commits = Commits.new
9
- @committers = Committers.new
10
9
  @teams = Teams.new
10
+ @committers = teams.committers
11
11
  @repositories = Repositories.new
12
- add_commits(commits)
12
+ end
13
+
14
+ def configure(teams, repositories)
15
+ @teams = teams
16
+ @committers = teams.committers
17
+ @repositories = repositories
13
18
  end
14
19
 
15
20
  def add_commit(commit)
@@ -9,12 +9,11 @@ class Committer
9
9
  @commits = Commits.new
10
10
  end
11
11
 
12
- def self.create_committer(login, firstname, lastname, email, team)
12
+ def self.create_committer(login, firstname, lastname, email)
13
13
  committer = Committer.new(login)
14
14
  committer.first_name = firstname
15
15
  committer.last_name = lastname
16
16
  committer.email = email
17
- committer.team = team
18
17
  committer
19
18
  end
20
19
 
@@ -47,6 +46,14 @@ class Committer
47
46
  @commits.amount_of_commits_to_repository_in_week(name, week_start)
48
47
  end
49
48
 
49
+ def committed_repositories
50
+ repositories = []
51
+ commits.each do |commit|
52
+ repositories.push(commit.repository)
53
+ end
54
+ repositories.uniq
55
+ end
56
+
50
57
  def ==(committer)
51
58
  username == committer.username &&
52
59
  first_name == committer.first_name &&
@@ -77,6 +84,12 @@ class Committers
77
84
  @committers[name] ||= Committer.new(name)
78
85
  end
79
86
 
87
+ def each
88
+ @committers.values.each do |committer|
89
+ yield committer
90
+ end
91
+ end
92
+
80
93
  def amount
81
94
  @committers.size
82
95
  end
@@ -4,5 +4,32 @@ class RepositoryLister
4
4
 
5
5
  def list(commit_history)
6
6
 
7
+ teams_and_repositories = collect_teams_and_repositories_they_committed_to(commit_history)
8
+
9
+ if teams_and_repositories.empty?
10
+ puts "No teams committed in any of the repositories"
11
+ return
12
+ end
13
+
14
+ print_teams_commit_to_which_repository(teams_and_repositories)
15
+ end
16
+
17
+ def collect_teams_and_repositories_they_committed_to(commit_history)
18
+ teams_and_repositories = {}
19
+ commit_history.teams.each do |team|
20
+ repositories = team.committed_repositories
21
+ teams_and_repositories[team.name] = repositories unless repositories.empty?
22
+ end
23
+ teams_and_repositories
24
+ end
25
+
26
+ def print_teams_commit_to_which_repository(teams_and_repositories)
27
+ teams_and_repositories.each do |team, repositories|
28
+ repositories_string = ""
29
+ repositories.each do |repository|
30
+ repositories_string += " " + repository.name + "\n"
31
+ end
32
+ puts "Team \"#{team}\" committed in:\n" + repositories_string
33
+ end
7
34
  end
8
35
  end
@@ -4,7 +4,8 @@ class SVNDataCollector
4
4
 
5
5
  attr_reader :config
6
6
 
7
- def initialize(config)
7
+ def initialize(config, commit_history = CommitHistory.new)
8
+ @commit_history = commit_history
8
9
  @config = config
9
10
  end
10
11
 
@@ -40,11 +41,10 @@ class SVNDataCollector
40
41
  end
41
42
 
42
43
  def collect_commit_history(repositories)
43
- commit_history = CommitHistory.new
44
44
  repositories.each { | repository|
45
- commit_history.add_commits(collect_commits_for_repository(repository))
45
+ @commit_history.add_commits(collect_commits_for_repository(repository))
46
46
  }
47
- commit_history
47
+ @commit_history
48
48
  end
49
49
 
50
50
  end
@@ -13,6 +13,10 @@ class Team
13
13
  member.team = self
14
14
  end
15
15
 
16
+ def add_members(members)
17
+ members.each { |member| add_member(member) }
18
+ end
19
+
16
20
  def members
17
21
  @members.values
18
22
  end
@@ -38,6 +42,16 @@ class Team
38
42
  def ==(team)
39
43
  name == team.name && members == team.members
40
44
  end
45
+
46
+ def committed_repositories
47
+
48
+ repositories = []
49
+
50
+ each_member do |member|
51
+ repositories += member.committed_repositories
52
+ end
53
+ repositories.uniq
54
+ end
41
55
  end
42
56
 
43
57
  class Teams
@@ -62,6 +76,16 @@ class Teams
62
76
  }
63
77
  end
64
78
 
79
+ def committers
80
+ committers = Committers.new
81
+ each_member { |team, committer| committers.add(committer) }
82
+ committers
83
+ end
84
+
85
+ def empty?
86
+ @teams.empty?
87
+ end
88
+
65
89
  def map(&block)
66
90
  @teams.values.map(&block)
67
91
  end
@@ -1,4 +1,4 @@
1
1
 
2
2
  module Codespicuous
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.2"
4
4
  end
@@ -37,27 +37,23 @@ describe "Codespicuous command line" do
37
37
  it "configures the config data" do
38
38
  configurator = CodespicuousConfigurator.new(subject.config)
39
39
  repositories = Repositories.new
40
- committers = Committers.new
41
40
  teams = Teams.new
42
41
 
43
42
  expect(CodespicuousConfigurator).to receive(:new).and_return(configurator)
44
43
  expect(configurator).to receive(:configure).with(["argv"]).and_return(true)
45
44
 
46
45
  expect(configurator).to receive(:repositories).and_return(repositories)
47
- expect(configurator).to receive(:committers).and_return(committers)
48
46
  expect(configurator).to receive(:teams).and_return(teams)
47
+ expect(subject.commit_history).to receive(:configure).with(teams, repositories)
49
48
 
50
49
  subject.configure(["argv"])
51
- expect(subject.committers).to be committers
52
- expect(subject.repositories).to be repositories
53
- expect(subject.teams).to be teams
54
50
  end
55
51
 
56
52
  it "collects the input data" do
57
53
  collector = SVNDataCollector.new(subject.config)
58
54
  commit_history = CommitHistory.new
59
55
  expect(SVNDataCollector).to receive(:new).and_return(collector)
60
- expect(collector).to receive(:collect_commit_history).with(subject.repositories).and_return(commit_history)
56
+ expect(collector).to receive(:collect_commit_history).with(commit_history.repositories).and_return(commit_history)
61
57
 
62
58
  subject.collect
63
59
 
@@ -130,14 +130,14 @@ describe "CodepicuousConfigurator reads all the config files and provides the da
130
130
  context "Parsing the teams and committers" do
131
131
 
132
132
  before (:each) do
133
+ @committer_bas = Committer.create_committer("basvodde", "Bas", "Vodde", "basv@wow.com")
133
134
  @team_wine = Team.new("Wine")
134
- @committer_bas = Committer.create_committer("basvodde", "Bas", "Vodde", "basv@wow.com", @team_wine)
135
+ @team_wine.add_member(@committer_bas)
135
136
  end
136
137
 
137
138
  it "can have no committers and teams. Just empty then" do
138
139
  subject.postprocess_yaml_configuration_committers({})
139
140
 
140
- expect(subject.committers).to eq Committers.new
141
141
  expect(subject.teams).to eq Teams.new
142
142
  end
143
143
 
@@ -160,15 +160,17 @@ describe "CodepicuousConfigurator reads all the config files and provides the da
160
160
  teams = Teams.new
161
161
  teams.add(@team_wine)
162
162
 
163
- expect(subject.committers).to eq committers
164
163
  expect(subject.teams).to eq teams
165
164
 
166
165
  end
167
166
 
168
167
  it "will not bother checking the CSV file when it found committers already" do
169
- committers = Committers.new
170
- committers.add(@committer_bas)
171
- expect(subject).to receive(:committers).and_return(committers)
168
+ teams = Teams.new
169
+ team = Team.new("Wine")
170
+ team.add_member(@committer_bas)
171
+ teams.add(team)
172
+
173
+ expect(subject).to receive(:teams).and_return(teams)
172
174
  expect(File).not_to receive(:exist?)
173
175
 
174
176
  subject.find_alternative_configuration_files_for_committers
@@ -179,7 +181,7 @@ describe "CodepicuousConfigurator reads all the config files and provides the da
179
181
 
180
182
  subject.find_alternative_configuration_files_for_committers
181
183
 
182
- expect(subject.committers).to eq Committers.new
184
+ expect(subject.teams).to eq Teams.new
183
185
  end
184
186
 
185
187
  it "will read the CSV file when it exists" do
@@ -190,10 +192,12 @@ describe "CodepicuousConfigurator reads all the config files and provides the da
190
192
 
191
193
  subject.find_alternative_configuration_files_for_committers
192
194
 
193
- committers = Committers.new
194
- committers.add(@committer_bas)
195
+ teams = Teams.new
196
+ team = Team.new("Wine")
197
+ team.add_member(@committer_bas)
198
+ teams.add(team)
195
199
 
196
- expect(subject.committers).to eq committers
200
+ expect(subject.teams).to eq teams
197
201
  end
198
202
 
199
203
  end
@@ -8,19 +8,20 @@ describe "The committers and the teams that we're examining" do
8
8
  @committers = Committers.new
9
9
  @teams = Teams.new
10
10
 
11
- wine = Team.new("Wine")
12
- cheese = Team.new("Cheese")
13
11
 
14
- bas = Committer.create_committer("basvodde", "Bas", "Vodde", "basv@wow.com", wine)
15
- janne = Committer.create_committer("janne", "Janne", "Yeah", "janne@yeah.com", cheese)
16
- daniel = Committer.create_committer("daniel", "Daniel", "Hum", "daniel@hum.com", wine)
12
+ bas = Committer.create_committer("basvodde", "Bas", "Vodde", "basv@wow.com")
13
+ janne = Committer.create_committer("janne", "Janne", "Yeah", "janne@yeah.com")
14
+ daniel = Committer.create_committer("daniel", "Daniel", "Hum", "daniel@hum.com")
17
15
 
18
16
  @committers.add(bas)
19
17
  @committers.add(daniel)
20
18
  @committers.add(janne)
21
19
 
20
+ wine = Team.new("Wine")
22
21
  wine.add_member(bas)
23
22
  wine.add_member(daniel)
23
+
24
+ cheese = Team.new("Cheese")
24
25
  cheese.add_member(janne)
25
26
 
26
27
  @teams.add(wine)
@@ -48,18 +49,23 @@ describe "The committers and the teams that we're examining" do
48
49
  end
49
50
 
50
51
  it "can compare two committers" do
52
+ bas = Committer.create_committer("basv", "Bas", "Vodde", "basv@wow.com")
53
+ dobbel_bas = Committer.create_committer("basv", "Bas", "Vodde", "basv@wow.com")
54
+
51
55
  team = Team.new("team")
52
- bas = Committer.create_committer("basv", "Bas", "Vodde", "basv@wow.com", team)
53
- dobbel_bas = Committer.create_committer("basv", "Bas", "Vodde", "basv@wow.com", team)
56
+ team.add_member(bas)
57
+ team.add_member(dobbel_bas)
54
58
 
55
59
  expect(bas).to eq dobbel_bas
56
60
  end
57
61
 
58
62
  it "can compare two committers that aren't equal" do
59
- team = Team.new("team")
60
- bas = Committer.create_committer("basv", "Bas", "Fake", "basv@wow.com", team)
61
- dobbel_bas = Committer.create_committer("basv", "Bas", "Vodde", "basv@wow.com", team)
63
+ bas = Committer.create_committer("basv", "Bas", "Fake", "basv@wow.com")
64
+ dobbel_bas = Committer.create_committer("basv", "Bas", "Vodde", "basv@wow.com")
62
65
 
66
+ team = Team.new("team")
67
+ team.add_member(bas)
68
+ team.add_member(dobbel_bas)
63
69
  expect(bas).not_to eq dobbel_bas
64
70
  end
65
71
  end
@@ -35,6 +35,7 @@ describe "Integration tests using offline logs from the filezilla project" do
35
35
  expect($stdout).to receive(:puts).with("Getting svn log from repository: filezilla")
36
36
  expect($stdout).to receive(:puts).with("Getting svn log from repository: xiph")
37
37
  expect($stdout).to receive(:puts).with("Stage 3: Listing repositories committed to")
38
+ expect($stdout).to receive(:puts).with("Team \"wine\" committed in:\n filezilla\n")
38
39
 
39
40
  load @codespicuous_script
40
41
  end
@@ -0,0 +1,23 @@
1
+
2
+ describe "listing which repositories the team committed to" do
3
+
4
+ subject { RepositoryLister.new }
5
+
6
+ it "informs that the team didn't commit to any of the repositories" do
7
+
8
+ expect(subject).to receive(:puts).with("No teams committed in any of the repositories")
9
+ subject.list(CommitHistory.new)
10
+ end
11
+
12
+ it "informs that one team has committed in one repository" do
13
+ commit_history = CommitHistoryBuilder.new.
14
+ in_repository("repo").
15
+ commits_of("basvodde").of_team("Wine").
16
+ at("2016-04-18").times(2).
17
+ build
18
+
19
+ expect(subject).to receive(:puts).with("Team \"Wine\" committed in:\n repo\n")
20
+ subject.list(commit_history)
21
+ end
22
+
23
+ end
@@ -73,7 +73,9 @@ describe "Collecting data from SVN" do
73
73
  expect(subject).to receive(:collect_commits_for_repository).with(@heh_repository).and_return(heh_commits)
74
74
  expect(subject).to receive(:collect_commits_for_repository).with(wow_repository).and_return(wow_commits)
75
75
 
76
- expect(subject.collect_commit_history(repositories)).to eq (CommitHistory.new(heh_commits + wow_commits))
76
+ commit_history = CommitHistory.new
77
+ commit_history.add_commits(heh_commits + wow_commits)
78
+ expect(subject.collect_commit_history(repositories)).to eq (commit_history)
77
79
  end
78
80
 
79
81
  it "Should write the svn logs to the svnlog directory" do
@@ -2,12 +2,13 @@
2
2
  describe "teams" do
3
3
 
4
4
  it "spec_name" do
5
+ bas = Committer.create_committer("basv", "Bas", "Vodde", "basv@wow.com")
6
+
5
7
  team = Team.new("team")
6
- bas = Committer.create_committer("basv", "Bas", "Vodde", "basv@wow.com", team)
7
8
  team.add_member(bas)
8
9
 
10
+ bas_dobbel = Committer.create_committer("basv", "Bas", "Vodde", "basv@wow.com")
9
11
  team_dobbel = Team.new("team")
10
- bas_dobbel = Committer.create_committer("basv", "Bas", "Vodde", "basv@wow.com", team)
11
12
  team_dobbel.add_member(bas_dobbel)
12
13
 
13
14
  expect(team).to eq team_dobbel
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: codespicuous
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bas Vodde
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-15 00:00:00.000000000 Z
11
+ date: 2017-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -61,7 +61,8 @@ dependencies:
61
61
  description: Codespicuous is a tool for generating several different metrics from
62
62
  codebases to gain insight in how the teams are working.
63
63
  email: basv@odd-e.com
64
- executables: []
64
+ executables:
65
+ - codespicuous
65
66
  extensions: []
66
67
  extra_rdoc_files: []
67
68
  files:
@@ -111,6 +112,7 @@ files:
111
112
  - spec/metrics_generator_daniel_spec.rb
112
113
  - spec/metrics_generator_spec.rb
113
114
  - spec/repositories_spec.rb
115
+ - spec/repository_lister_spec.rb
114
116
  - spec/svn_client_spec.rb
115
117
  - spec/svn_data_collector_spec.rb
116
118
  - spec/svn_log_parser_spec.rb