codespicuous 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: []