codespicuous 0.0.1 → 0.0.2

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 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