codespicuous 0.0.1

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.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +7 -0
  3. data/LICENSE +29 -0
  4. data/README.md +2 -0
  5. data/Rakefile +6 -0
  6. data/bin/codespicuous +4 -0
  7. data/bin/filezilla/codespicuous.yaml +23 -0
  8. data/bin/filezilla/committers.csv +4 -0
  9. data/bin/filezilla/svnlog/filezilla.log +3939 -0
  10. data/bin/filezilla/svnlog/python.log +3 -0
  11. data/bin/filezilla/svnlog/xiph.log +265 -0
  12. data/codespicuous.gemspec +22 -0
  13. data/lib/codespicuous.rb +38 -0
  14. data/lib/codespicuous/codespicuous.rb +55 -0
  15. data/lib/codespicuous/codespicuous_config.rb +35 -0
  16. data/lib/codespicuous/codespicuousconfigurator.rb +136 -0
  17. data/lib/codespicuous/commandrunner.rb +13 -0
  18. data/lib/codespicuous/commithistory.rb +71 -0
  19. data/lib/codespicuous/commithistory_builder.rb +49 -0
  20. data/lib/codespicuous/commits.rb +147 -0
  21. data/lib/codespicuous/commitstatistics.rb +245 -0
  22. data/lib/codespicuous/committer.rb +105 -0
  23. data/lib/codespicuous/danielparser.rb +31 -0
  24. data/lib/codespicuous/dateutil.rb +18 -0
  25. data/lib/codespicuous/metrics_generator.rb +22 -0
  26. data/lib/codespicuous/metrics_generator_csv.rb +67 -0
  27. data/lib/codespicuous/metrics_generator_daniel.rb +13 -0
  28. data/lib/codespicuous/participantsparser_from_csv.rb +37 -0
  29. data/lib/codespicuous/repositories.rb +80 -0
  30. data/lib/codespicuous/repository_lister.rb +8 -0
  31. data/lib/codespicuous/svn_client.rb +14 -0
  32. data/lib/codespicuous/svn_data_collector.rb +50 -0
  33. data/lib/codespicuous/svn_log_parser.rb +100 -0
  34. data/lib/codespicuous/teams.rb +99 -0
  35. data/lib/codespicuous/version.rb +4 -0
  36. data/spec/codespicuous_spec.rb +81 -0
  37. data/spec/codespicuousconfigurator_spec.rb +202 -0
  38. data/spec/commithistories_data.rb +46 -0
  39. data/spec/commithistory_spec.rb +57 -0
  40. data/spec/commits_spec.rb +93 -0
  41. data/spec/committers_spec.rb +66 -0
  42. data/spec/danielparser_spec.rb +12 -0
  43. data/spec/integration_filezilla_spec.rb +41 -0
  44. data/spec/metrics_generator_csv_spec.rb +91 -0
  45. data/spec/metrics_generator_daniel_spec.rb +10 -0
  46. data/spec/metrics_generator_spec.rb +35 -0
  47. data/spec/repositories_spec.rb +29 -0
  48. data/spec/svn_client_spec.rb +16 -0
  49. data/spec/svn_data_collector_spec.rb +93 -0
  50. data/spec/svn_log_parser_spec.rb +141 -0
  51. data/spec/teams_spec.rb +16 -0
  52. metadata +142 -0
@@ -0,0 +1,29 @@
1
+
2
+ require 'codespicuous.rb'
3
+
4
+ describe "The repositories that we are examining" do
5
+
6
+ it "can comparing two repositories and they are the same" do
7
+ repo1 = Repository.new("repo", "url")
8
+ repo2 = Repository.new("repo", "url")
9
+
10
+ expect(repo1).to eq(repo2)
11
+ end
12
+
13
+ it "can comparing two repositories that aren't the same" do
14
+ repo1 = Repository.new("repo1", "url")
15
+ repo2 = Repository.new("repo2", "url")
16
+
17
+ expect(repo1).not_to eq(repo2)
18
+ end
19
+
20
+ it "can comparing two repositories of which one has commits will throw an exception" do
21
+ repo1 = Repository.new("repo1", "url")
22
+ repo2 = Repository.new("repo1", "url")
23
+
24
+ repo1.add_commit(Commit.new)
25
+
26
+ expect{repo1 == repo2}.to raise_error(SameRepositoriesWithDifferentCommitsError)
27
+ end
28
+ end
29
+
@@ -0,0 +1,16 @@
1
+
2
+ describe "Interface towards the command line svn" do
3
+
4
+ it "Should be able to retrieve an xml log" do
5
+ svn = SVNClient.new
6
+ xmllog = double(:xmllog)
7
+
8
+ now = DateTime.new(1978)
9
+
10
+ expect(AttemptTo).to receive(:attempt_to).with('svn log: "Heh"', 5).and_yield
11
+ expect(CommandRunner).to receive(:run).with("svn log Heh -r{1977-01-01}:{1978-01-01} --xml").and_return(xmllog)
12
+
13
+ svn.repository("Heh")
14
+ expect(svn.log_xml(now.prev_year, now)).to eq(xmllog)
15
+ end
16
+ end
@@ -0,0 +1,93 @@
1
+
2
+ describe "Collecting data from SVN" do
3
+
4
+ subject { SVNDataCollector.new(CodespicuousConfig.new) }
5
+
6
+ before (:each) do
7
+ @heh_repository = Repository.new("heh", "https://heh")
8
+ @xmllog = double(:xmllog)
9
+ end
10
+
11
+ it "should get the xml log from the svn client" do
12
+ svnclient = double(:svnclient)
13
+
14
+ expect(SVNClient).to receive(:new).and_return(svnclient)
15
+ expect(DateTime).to receive(:now).and_return(DateTime.new(2001))
16
+
17
+ expect(svnclient).to receive(:repository).with(@heh_repository.url)
18
+ expect(svnclient).to receive(:log_xml).with(DateTime.new(2000), DateTime.new(2001)).and_return(@xmllog)
19
+
20
+ expect(subject.retrieve_svn_log_from(@heh_repository)).to eq @xmllog
21
+ end
22
+
23
+ it "should get the xml log from file when offline" do
24
+ subject.config.offline = true
25
+ expect(File).to receive(:read).with("svnlog/heh.log").and_return(@xmllog)
26
+ expect(subject.retrieve_svn_log_from(@heh_repository)).to eq @xmllog
27
+ end
28
+
29
+ it "should parse the xml log that was retrieved from the svn client" do
30
+
31
+ svnxmlparser = double(:parser)
32
+ commits = Commits.new
33
+
34
+ expect(SVNLogParser).to receive(:new).and_return(svnxmlparser)
35
+ expect(svnxmlparser).to receive(:parse).with(@xmllog)
36
+ expect(svnxmlparser).to receive(:commits).and_return(commits)
37
+
38
+ expect(subject.retrieve_commits_from_log(@xmllog)).to eq commits
39
+ end
40
+
41
+ it "Should collect the log for one repository" do
42
+
43
+ commit = Commit.new
44
+ commits = Commits.new
45
+ commits.add(commit)
46
+
47
+ expect(subject).to receive(:puts).with("Getting svn log from repository: heh")
48
+ expect(subject).to receive(:retrieve_svn_log_from).with(@heh_repository).and_return(@xmllog)
49
+ expect(subject).to receive(:save_svn_log).with(@heh_repository, @xmllog)
50
+ expect(subject).to receive(:retrieve_commits_from_log).with(@xmllog).and_return(commits)
51
+
52
+ expect(subject.collect_commits_for_repository(@heh_repository)).to eq (commits)
53
+ expect(commit.repository).to eq @heh_repository
54
+ end
55
+
56
+ def create_commits_with_one_commit_in_repository repository
57
+ commit = Commit.new
58
+ commit.repository = repository
59
+ commits = Commits.new
60
+ commits.add(commit)
61
+ commits
62
+ end
63
+
64
+ it "Should collect the log for each repository and add the commits" do
65
+ repositories = Repositories.new
66
+ wow_repository = Repository.new("wow", "https://wow")
67
+ repositories.add(@heh_repository)
68
+ repositories.add(wow_repository)
69
+
70
+ heh_commits = create_commits_with_one_commit_in_repository(@heh_repository)
71
+ wow_commits = create_commits_with_one_commit_in_repository(wow_repository)
72
+
73
+ expect(subject).to receive(:collect_commits_for_repository).with(@heh_repository).and_return(heh_commits)
74
+ expect(subject).to receive(:collect_commits_for_repository).with(wow_repository).and_return(wow_commits)
75
+
76
+ expect(subject.collect_commit_history(repositories)).to eq (CommitHistory.new(heh_commits + wow_commits))
77
+ end
78
+
79
+ it "Should write the svn logs to the svnlog directory" do
80
+ expect(Dir).to receive(:exists?).with("svnlog").and_return(true)
81
+ expect(File).to receive(:write).with("svnlog/heh.log", "xmllog")
82
+
83
+ subject.save_svn_log(@heh_repository, "xmllog")
84
+ end
85
+
86
+ it "Should write the svn logs to the svnlog directory which must be created first" do
87
+ expect(Dir).to receive(:exists?).with("svnlog").and_return(false)
88
+ expect(Dir).to receive(:mkdir).with("svnlog")
89
+ expect(File).to receive(:write)
90
+
91
+ subject.save_svn_log(@heh_repository, "xmllog")
92
+ end
93
+ end
@@ -0,0 +1,141 @@
1
+
2
+ describe "parsing the SVN logs" do
3
+
4
+ def log(text)
5
+ '<?xml version="1.0" encoding="UTF-8"?><log>' + text + '</log>'
6
+ end
7
+
8
+ def logentry(revision, author, date, message, additional_tags, paths)
9
+ "<logentry revision=\"#{revision}\"><author>#{author}</author><date>#{date}</date>#{additional_tags} <paths>" + paths + "</paths><msg>#{message}</msg></logentry>"
10
+ end
11
+
12
+ def path(action, propmods, textmods, kind, file)
13
+ "<path action=\"#{action}\" prop-mods=\"#{propmods}\" text-mods=\"#{textmods}\" kind=\"#{kind}\">#{file}</path>"
14
+ end
15
+
16
+ def log_with_default_logentry(additional_tags, paths)
17
+ log(logentry(1, "someone", "2017-01-01", "message", additional_tags, paths))
18
+ end
19
+
20
+ def log_with_paths(paths)
21
+ log_with_default_logentry("", paths)
22
+ end
23
+
24
+ subject { SVNLogParser.new }
25
+
26
+ context "SVN Log with 2 commits and 3 modified files" do
27
+ before(:each) do
28
+
29
+ svn_log_xml = log(
30
+ logentry(10, "basvodde", "2016-01-04T01:59:13", "Summary:optimize implementation.", "",
31
+ path("M", true, true, "file", "/trunk/header.hpp")) +
32
+ logentry(5, "daniel", "2016-01-04T04:37:03.111034Z", "Exciting message", "",
33
+ path("A", false, true, "file", "/trunk/otherheader.hpp") +
34
+ path("M", false, true, "file", "/trunk/implementation.cpp")))
35
+
36
+ subject.xml_to_parse(svn_log_xml)
37
+ end
38
+
39
+ it "parses SVN log files" do
40
+ subject.parse
41
+ commits = subject.commits
42
+ expect(commits.amount).to eq 2
43
+ end
44
+
45
+ it "knows Bas had one commit" do
46
+ subject.parse
47
+ expect(subject.commits.find_by_committer("basvodde").amount).to eq 1
48
+ end
49
+
50
+ it "knows Bas modified properties" do
51
+ subject.parse
52
+ expect(subject.commits.find_commit(nil, "10").changes[0].changed_property?).to be true
53
+ end
54
+
55
+ it "knows all the details of the commit" do
56
+ subject.parse
57
+ commit = subject.commits.find_commit(nil, "10")
58
+ expect(commit.message).to eq "Summary:optimize implementation."
59
+ expect(commit.author).to eq "basvodde"
60
+ expect(commit.date).to eq DateTime.new(2016,1,4,1,59,13)
61
+ end
62
+
63
+ it "knows which files were changed in the commit" do
64
+ commit = subject.parse.commits.find_commit(nil, "5")
65
+ expect(commit.changes.size).to eq 2
66
+ expect(commit.changes[0].type).to eq :added
67
+ expect(commit.changes[1].type).to eq :modified
68
+ expect(commit.changes[1].file).to eq "/trunk/implementation.cpp"
69
+ end
70
+ end
71
+
72
+ context "Warn for XML elements that aren't implemented yet :)" do
73
+
74
+ it "Warns on non-log entries" do
75
+ expect{subject.parse(log('<notlogentry></notlogentry>'))}.to raise_error("Unexpected log entry: notlogentry")
76
+ end
77
+
78
+ it "Warns on unexpected attributes to logentry" do
79
+ expect{subject.parse(log('<logentry shouldntbehere="10"></logentry>'))}.to raise_error("Unexpected attributes log entry: shouldntbehere")
80
+ end
81
+
82
+ it "Warns on unexpected elements to logentry" do
83
+ expect{subject.parse(log_with_default_logentry('<huh></huh>', ""))}.to raise_error("Unexpected element in log entry: huh")
84
+ end
85
+
86
+ it "Warns on unexpected elements in path" do
87
+ expect{subject.parse(log_with_default_logentry("", '<path><uhm></uhm></path>'))}.to raise_error("Unexpected element in path: uhm")
88
+ end
89
+
90
+ it "Warns on unexpected attributes in path" do
91
+ expect{subject.parse(log_with_default_logentry("", '<path bleh="10"></path>'))}.to raise_error("Unexpected attributes in path: bleh")
92
+ end
93
+
94
+ it "Warns if attributes in path have unexpected values" do
95
+ expect{subject.parse(log_with_paths('<path action="T"></path>'))}.to raise_error("Unexpected value to attribute action in path: T")
96
+ expect{subject.parse(log_with_paths('<path action="M" prop-mods="false" text-mods="true" kind="space"></path>'))}.to raise_error("Unexpected value to attribute kind in path: space")
97
+ end
98
+
99
+ it "Warns by printing output on strange text-mods value. Needs to be checked what to do with it." do
100
+ expect(subject).to receive(:puts).with('Unexpected value to attribute text-mods in path: false')
101
+ subject.parse(log_with_paths('<path action="M" prop-mods="false" text-mods="false" kind="file"></path>'))
102
+ end
103
+ end
104
+
105
+ context "Less common svn log elements" do
106
+
107
+ it "Can deal with copyfrom-path" do
108
+ xmllog = log_with_paths('<path action="A" prop-mods="false" text-mods="true" kind="file" copyfrom-path="originalfile.cpp" copyfrom-rev="18">newfile</path>')
109
+ subject.parse(xmllog)
110
+ expect(subject.commits[0].changes[0].copyfrom).to eq "originalfile.cpp"
111
+ expect(subject.commits[0].changes[0].copyrev).to eq "18"
112
+ end
113
+
114
+ it "Can deal with deleted files" do
115
+ xmllog = log_with_paths(path("D", false, true, "file", "/trunk/header.hpp"))
116
+ subject.parse(xmllog)
117
+ expect(subject.commits[0].changes[0].type).to eq :deleted
118
+ end
119
+
120
+ it "Can deal with renames files" do
121
+ xmllog = log_with_paths(path("R", false, false, "file", "/trunk/header.hpp"))
122
+ subject.parse(xmllog)
123
+ expect(subject.commits[0].changes[0].type).to eq :renamed
124
+ end
125
+
126
+ it "text-mods can be false when the file is deleted" do
127
+ xmllog = log_with_paths(path("D", false, false, "file", "/trunk/header.hpp"))
128
+ subject.parse(xmllog)
129
+
130
+ # No exception
131
+ end
132
+
133
+ it "can add directories" do
134
+ xmllog = log_with_paths(path("A", false, false, "dir", "/trunk"))
135
+ subject.parse(xmllog)
136
+ expect(subject.commits[0].changes[0].kind).to eq :dir
137
+ end
138
+
139
+ end
140
+
141
+ end
@@ -0,0 +1,16 @@
1
+
2
+ describe "teams" do
3
+
4
+ it "spec_name" do
5
+ team = Team.new("team")
6
+ bas = Committer.create_committer("basv", "Bas", "Vodde", "basv@wow.com", team)
7
+ team.add_member(bas)
8
+
9
+ team_dobbel = Team.new("team")
10
+ bas_dobbel = Committer.create_committer("basv", "Bas", "Vodde", "basv@wow.com", team)
11
+ team_dobbel.add_member(bas_dobbel)
12
+
13
+ expect(team).to eq team_dobbel
14
+ end
15
+
16
+ end
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: codespicuous
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Bas Vodde
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-08-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 2.0.0
37
+ type: :development
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '2.0'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 2.0.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: attempt_to
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ description: Codespicuous is a tool for generating several different metrics from
62
+ codebases to gain insight in how the teams are working.
63
+ email: basv@odd-e.com
64
+ executables: []
65
+ extensions: []
66
+ extra_rdoc_files: []
67
+ files:
68
+ - Gemfile
69
+ - LICENSE
70
+ - README.md
71
+ - Rakefile
72
+ - bin/codespicuous
73
+ - bin/filezilla/codespicuous.yaml
74
+ - bin/filezilla/committers.csv
75
+ - bin/filezilla/svnlog/filezilla.log
76
+ - bin/filezilla/svnlog/python.log
77
+ - bin/filezilla/svnlog/xiph.log
78
+ - codespicuous.gemspec
79
+ - lib/codespicuous.rb
80
+ - lib/codespicuous/codespicuous.rb
81
+ - lib/codespicuous/codespicuous_config.rb
82
+ - lib/codespicuous/codespicuousconfigurator.rb
83
+ - lib/codespicuous/commandrunner.rb
84
+ - lib/codespicuous/commithistory.rb
85
+ - lib/codespicuous/commithistory_builder.rb
86
+ - lib/codespicuous/commits.rb
87
+ - lib/codespicuous/commitstatistics.rb
88
+ - lib/codespicuous/committer.rb
89
+ - lib/codespicuous/danielparser.rb
90
+ - lib/codespicuous/dateutil.rb
91
+ - lib/codespicuous/metrics_generator.rb
92
+ - lib/codespicuous/metrics_generator_csv.rb
93
+ - lib/codespicuous/metrics_generator_daniel.rb
94
+ - lib/codespicuous/participantsparser_from_csv.rb
95
+ - lib/codespicuous/repositories.rb
96
+ - lib/codespicuous/repository_lister.rb
97
+ - lib/codespicuous/svn_client.rb
98
+ - lib/codespicuous/svn_data_collector.rb
99
+ - lib/codespicuous/svn_log_parser.rb
100
+ - lib/codespicuous/teams.rb
101
+ - lib/codespicuous/version.rb
102
+ - spec/codespicuous_spec.rb
103
+ - spec/codespicuousconfigurator_spec.rb
104
+ - spec/commithistories_data.rb
105
+ - spec/commithistory_spec.rb
106
+ - spec/commits_spec.rb
107
+ - spec/committers_spec.rb
108
+ - spec/danielparser_spec.rb
109
+ - spec/integration_filezilla_spec.rb
110
+ - spec/metrics_generator_csv_spec.rb
111
+ - spec/metrics_generator_daniel_spec.rb
112
+ - spec/metrics_generator_spec.rb
113
+ - spec/repositories_spec.rb
114
+ - spec/svn_client_spec.rb
115
+ - spec/svn_data_collector_spec.rb
116
+ - spec/svn_log_parser_spec.rb
117
+ - spec/teams_spec.rb
118
+ homepage: https://github.com/basvodde/codespicuous
119
+ licenses:
120
+ - MIT
121
+ metadata: {}
122
+ post_install_message:
123
+ rdoc_options: []
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ required_rubygems_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ requirements: []
137
+ rubyforge_project:
138
+ rubygems_version: 2.6.10
139
+ signing_key:
140
+ specification_version: 4
141
+ summary: Codespicuous is a tool for generating team based metrics from code
142
+ test_files: []