metior 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +0 -2
- data/Gemfile.lock +0 -1
- data/lib/metior.rb +22 -16
- data/lib/metior/github/commit.rb +4 -4
- data/lib/metior/github/repository.rb +18 -16
- data/lib/metior/vcs.rb +3 -1
- data/lib/metior/version.rb +1 -1
- data/metior.gemspec +1 -0
- data/test/fixtures.rb +115 -0
- data/test/helper.rb +1 -0
- data/test/test_git.rb +94 -0
- data/test/test_github.rb +103 -6
- data/test/test_repository.rb +0 -104
- metadata +6 -10
- data/test/mock_vcs/actor.rb +0 -28
- data/test/mock_vcs/commit.rb +0 -53
- data/test/mock_vcs/repository.rb +0 -72
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/lib/metior.rb
CHANGED
@@ -5,12 +5,6 @@
|
|
5
5
|
|
6
6
|
require 'bundler'
|
7
7
|
|
8
|
-
libdir = File.dirname(__FILE__)
|
9
|
-
Dir.chdir libdir do
|
10
|
-
Bundler.setup
|
11
|
-
end
|
12
|
-
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
13
|
-
|
14
8
|
require 'core_ext/object'
|
15
9
|
require 'metior/git'
|
16
10
|
require 'metior/github'
|
@@ -22,6 +16,14 @@ require 'metior/version'
|
|
22
16
|
# @author Sebastian Staudt
|
23
17
|
module Metior
|
24
18
|
|
19
|
+
# Returns the Bundler runtime to access Metior's dependencies
|
20
|
+
#
|
21
|
+
# @return [Bundler::Runtime] The Bundler runtime instance
|
22
|
+
def self.runtime
|
23
|
+
@@runtime ||= Bundler::Runtime.new File.dirname(__FILE__),
|
24
|
+
Bundler.definition
|
25
|
+
end
|
26
|
+
|
25
27
|
# Creates a new repository for the given repository type and path
|
26
28
|
#
|
27
29
|
# @param [Symbol] type The type of the repository, e.g. `:git`
|
@@ -35,19 +37,23 @@ module Metior
|
|
35
37
|
# Calculates simplistic stats for the given repository and branch
|
36
38
|
#
|
37
39
|
# @param [Symbol] type The type of the repository, e.g. `:git`
|
38
|
-
# @param [
|
39
|
-
# @param [String]
|
40
|
-
#
|
40
|
+
# @param [Array<Object>] options The options for the repository
|
41
|
+
# @param [String, Range] range The range of commits for which the commits
|
42
|
+
# should be loaded. This may be given as a string
|
43
|
+
# (`'master..development'`), a range (`'master'..'development'`)
|
44
|
+
# or as a single ref (`'master'`). A single ref name means all
|
45
|
+
# commits reachable from that ref.
|
41
46
|
# @return [Hash] The calculated stats for the given repository and branch
|
42
|
-
def self.simple_stats(type,
|
43
|
-
|
44
|
-
branch
|
47
|
+
def self.simple_stats(type, *options)
|
48
|
+
arity = vcs(type)::Repository.instance_method(:initialize).arity
|
49
|
+
branch = options.delete_at arity
|
50
|
+
branch = vcs(type)::DEFAULT_BRANCH if branch.nil?
|
51
|
+
repo = repository type, *options
|
45
52
|
|
46
53
|
{
|
47
|
-
:
|
48
|
-
:
|
49
|
-
|
50
|
-
}
|
54
|
+
:commit_count => repo.commits(branch).size,
|
55
|
+
:top_contributors => repo.top_contributors(branch, 5),
|
56
|
+
}.merge Commit.activity(repo.commits(branch))
|
51
57
|
end
|
52
58
|
|
53
59
|
end
|
data/lib/metior/github/commit.rb
CHANGED
@@ -29,20 +29,20 @@ module Metior
|
|
29
29
|
|
30
30
|
@added_files = []
|
31
31
|
@additions = 0
|
32
|
-
@authored_date = commit.authored_date
|
33
|
-
@committed_date = commit.committed_date
|
32
|
+
@authored_date = Time.parse commit.authored_date
|
33
|
+
@committed_date = Time.parse commit.committed_date
|
34
34
|
@deleted_files = []
|
35
35
|
@deletions = 0
|
36
36
|
@id = commit.id
|
37
37
|
@message = commit.message
|
38
38
|
@modified_files = []
|
39
39
|
|
40
|
-
authors = repo.authors
|
40
|
+
authors = repo.authors range
|
41
41
|
@author = authors[Actor.id_for commit.author]
|
42
42
|
@author = Actor.new repo, commit.author if author.nil?
|
43
43
|
@author.add_commit self
|
44
44
|
|
45
|
-
committers = repo.committers
|
45
|
+
committers = repo.committers range
|
46
46
|
@committer = committers[Actor.id_for commit.committer]
|
47
47
|
@committer = Actor.new repo, commit.committer if @committer.nil?
|
48
48
|
@committer.add_commit self
|
@@ -57,37 +57,39 @@ module Metior
|
|
57
57
|
# or as a single ref (`'master'`). A single ref name means all
|
58
58
|
# commits reachable from that ref.
|
59
59
|
# @return [Array<Commit>] All commits in the given commit range
|
60
|
-
# @see #
|
60
|
+
# @see #load_ref_commits
|
61
61
|
def load_commits(range)
|
62
|
-
commits =
|
63
|
-
|
64
|
-
|
62
|
+
commits = load_ref_commits(range.last)
|
63
|
+
if range.first == ''
|
64
|
+
base_commits = []
|
65
|
+
else
|
66
|
+
base_commits = load_ref_commits(range.first).map! do |commit|
|
67
|
+
commit.id
|
68
|
+
end
|
65
69
|
end
|
66
70
|
commits.reject { |commit| base_commits.include? commit.id }
|
67
71
|
end
|
68
72
|
|
69
|
-
# This method uses Octokit to load all commits from the given
|
73
|
+
# This method uses Octokit to load all commits from the given ref
|
70
74
|
#
|
71
75
|
# Because of GitHub API limitations, the commits have to be loaded in
|
72
76
|
# batches.
|
73
77
|
#
|
74
78
|
# @note GitHub API is currently limited to 60 calls a minute, so you
|
75
|
-
# won't be able to query
|
76
|
-
#
|
77
|
-
# @param [String]
|
78
|
-
# @
|
79
|
-
# commits should be assigned
|
80
|
-
# @return [Array<Commit>] All commits from the given branch
|
79
|
+
# won't be able to query refs with more than 2100 commits (35
|
80
|
+
# commits per call).
|
81
|
+
# @param [String] ref The ref to load commits from
|
82
|
+
# @return [Array<Commit>] All commits from the given ref
|
81
83
|
# @see Octokit::Commits#commits
|
82
|
-
def
|
84
|
+
def load_ref_commits(ref)
|
83
85
|
commits = []
|
84
86
|
page = 1
|
85
87
|
begin
|
86
|
-
|
87
|
-
commits += Octokit.commits(@path,
|
88
|
+
loop do
|
89
|
+
commits += Octokit.commits(@path, ref, :page => page)
|
88
90
|
page += 1
|
89
|
-
end
|
90
|
-
rescue
|
91
|
+
end
|
92
|
+
rescue Faraday::Error::ResourceNotFound
|
91
93
|
end
|
92
94
|
commits
|
93
95
|
end
|
data/lib/metior/vcs.rb
CHANGED
data/lib/metior/version.rb
CHANGED
data/metior.gemspec
CHANGED
@@ -12,6 +12,7 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.summary = 'A source code history analyzer API'
|
13
13
|
s.description = 'Metior is a source code history analyzer that provides various statistics about a source code repository and its change over time.'
|
14
14
|
|
15
|
+
s.add_dependency 'bundler', '~> 1.0.14'
|
15
16
|
Bundler.definition.dependencies.each do |dep|
|
16
17
|
if dep.groups.include?(:development) || dep.groups.include?(:test)
|
17
18
|
s.add_development_dependency(dep.name, dep.requirement.to_s)
|
data/test/fixtures.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
# This code is free software; you can redistribute it and/or modify it under
|
2
|
+
# the terms of the new BSD License.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2011, Sebastian Staudt
|
5
|
+
|
6
|
+
require 'rash'
|
7
|
+
require 'time'
|
8
|
+
|
9
|
+
module Fixtures
|
10
|
+
|
11
|
+
@@commits = {}
|
12
|
+
|
13
|
+
def self.commits(range)
|
14
|
+
unless @@commits.key? range
|
15
|
+
file = File.open(File.expand_path("#{File.dirname(__FILE__)}/fixtures/mojombo-grit-master-1b2fe77.txt"), 'r')
|
16
|
+
file.set_encoding 'utf-8' if file.respond_to? :set_encoding
|
17
|
+
|
18
|
+
commits = []
|
19
|
+
|
20
|
+
commit = {}
|
21
|
+
file.lines.each do |line|
|
22
|
+
line.strip!
|
23
|
+
|
24
|
+
next if line.empty?
|
25
|
+
|
26
|
+
if line.match /^[AMD]\0/
|
27
|
+
commit[:files] = [] unless commit.key? :files
|
28
|
+
commit[:files] << line.split("\0")
|
29
|
+
elsif line.match /\d+\0\d+$/
|
30
|
+
commit[:impact] = line.split("\0")
|
31
|
+
else
|
32
|
+
line = line.split("\0")
|
33
|
+
ids = [line[0]]
|
34
|
+
ids += line[1][2..-2].split(', ') unless line[1].empty?
|
35
|
+
commit[:ids] = ids
|
36
|
+
commit[:info] = line[2..-1]
|
37
|
+
|
38
|
+
if commits.empty?
|
39
|
+
if !commit[:ids].include?(range.last)
|
40
|
+
commit = {}
|
41
|
+
next
|
42
|
+
end
|
43
|
+
elsif commit[:ids].include? range.first
|
44
|
+
break
|
45
|
+
end
|
46
|
+
|
47
|
+
if commit != {}
|
48
|
+
commits << commit
|
49
|
+
commit = {}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
@@commits[range] = commits
|
55
|
+
end
|
56
|
+
|
57
|
+
@@commits[range]
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.commits_as_grit_commits(range)
|
61
|
+
commits = commits(range)
|
62
|
+
|
63
|
+
commits.map do |commit|
|
64
|
+
grit_commit = Grit::Commit.new(
|
65
|
+
nil,
|
66
|
+
commit[:ids].first,
|
67
|
+
[],
|
68
|
+
nil,
|
69
|
+
Grit::Actor.new(commit[:info][4], commit[:info][5]),
|
70
|
+
Time.at(commit[:info][6].to_i),
|
71
|
+
Grit::Actor.new(commit[:info][1], commit[:info][2]),
|
72
|
+
Time.at(commit[:info][3].to_i),
|
73
|
+
commit[:info].first.lines.to_a
|
74
|
+
)
|
75
|
+
|
76
|
+
grit_commit.stubs(:diffs).returns []
|
77
|
+
|
78
|
+
stats = Hashie::Rash.new
|
79
|
+
if commit.key? :impact
|
80
|
+
stats.additions = commit[:impact].first.to_i
|
81
|
+
stats.deletions = commit[:impact].last.to_i
|
82
|
+
else
|
83
|
+
stats.additions = 0
|
84
|
+
stats.deletions = 0
|
85
|
+
end
|
86
|
+
grit_commit.stubs(:stats).returns stats
|
87
|
+
|
88
|
+
grit_commit
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.commits_as_rashies(range)
|
93
|
+
commits = commits(range)
|
94
|
+
|
95
|
+
commits.map do |commit|
|
96
|
+
Hashie::Rash.new({
|
97
|
+
:author => {
|
98
|
+
:email => commit[:info][4],
|
99
|
+
:login => commit[:info][5],
|
100
|
+
:name => commit[:info][5]
|
101
|
+
},
|
102
|
+
:authored_date => Time.at(commit[:info][6].to_i).to_s,
|
103
|
+
:committed_date => Time.at(commit[:info][3].to_i).to_s,
|
104
|
+
:committer => {
|
105
|
+
:email => commit[:info][1],
|
106
|
+
:login => commit[:info][2],
|
107
|
+
:name => commit[:info][2]
|
108
|
+
},
|
109
|
+
:id => commit[:ids].first,
|
110
|
+
:message => commit[:info].first,
|
111
|
+
})
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
data/test/helper.rb
CHANGED
data/test/test_git.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
#
|
4
4
|
# Copyright (c) 2011, Sebastian Staudt
|
5
5
|
|
6
|
+
require 'fixtures'
|
6
7
|
require 'helper'
|
7
8
|
|
8
9
|
class TestGit < Test::Unit::TestCase
|
@@ -19,4 +20,97 @@ class TestGit < Test::Unit::TestCase
|
|
19
20
|
|
20
21
|
end
|
21
22
|
|
23
|
+
context 'A Git repository' do
|
24
|
+
|
25
|
+
setup do
|
26
|
+
@repo = Metior::Git::Repository.new File.dirname(File.dirname(__FILE__))
|
27
|
+
@@grit_commits ||= Fixtures.commits_as_grit_commits(''..'master')
|
28
|
+
@commits_stub = Grit::Repo.any_instance.stubs :commits
|
29
|
+
@commits_stub.returns @@grit_commits
|
30
|
+
end
|
31
|
+
|
32
|
+
should 'be able to load all commits from the repository\'s default branch' do
|
33
|
+
commits = @repo.commits
|
34
|
+
assert_equal 460, commits.size
|
35
|
+
assert commits.all? { |commit| commit.is_a? Metior::Git::Commit }
|
36
|
+
|
37
|
+
head = commits.first
|
38
|
+
assert_equal '1b2fe77', head.id
|
39
|
+
end
|
40
|
+
|
41
|
+
should 'be able to load a range of commits from the repository' do
|
42
|
+
@commits_stub = Grit::Repo.any_instance.stubs :commits
|
43
|
+
api_response = Fixtures.commits_as_grit_commits('ef2870b'..'4c592b4')
|
44
|
+
@commits_stub.returns api_response
|
45
|
+
|
46
|
+
commits = @repo.commits 'ef2870b'..'4c592b4'
|
47
|
+
assert_equal 6, commits.size
|
48
|
+
assert commits.all? { |commit| commit.is_a? Metior::Git::Commit }
|
49
|
+
assert_equal '4c592b4', commits.first.id
|
50
|
+
assert_equal 'f0cc7f7', commits.last.id
|
51
|
+
end
|
52
|
+
|
53
|
+
should 'know the authors of the repository' do
|
54
|
+
authors = @repo.authors
|
55
|
+
assert_equal 37, authors.size
|
56
|
+
assert authors.values.all? { |author| author.is_a? Metior::Git::Actor }
|
57
|
+
|
58
|
+
assert_equal %w{
|
59
|
+
adam@therealadam.com aman@tmm1.net antonin@hildebrand.cz
|
60
|
+
bobbywilson0@gmail.com bryce@worldmedia.net cehoffman@gmail.com
|
61
|
+
chapados@sciencegeeks.org cho45@lowreal.net chris@ozmm.org
|
62
|
+
davetron5000@gmail.com david.kowis@rackspace.com dustin@spy.net
|
63
|
+
engel@engel.uk.to evil@che.lu gram.gibson@uky.edu
|
64
|
+
hiroshi3110@gmail.com igor@wiedler.ch johan@johansorensen.com
|
65
|
+
jos@catnook.com jpriddle@nevercraft.net kamal.fariz@gmail.com
|
66
|
+
koraktor@gmail.com mtraverso@acm.org ohnobinki@ohnopublishing.net
|
67
|
+
paul+git@mjr.org pjhyett@gmail.com rsanheim@gmail.com
|
68
|
+
rtomayko@gmail.com schacon@gmail.com scott@railsnewbie.com
|
69
|
+
technoweenie@gmail.com tim@dysinger.net tim@spork.in
|
70
|
+
tom@mojombo.com tom@taco.(none) voker57@gmail.com wayne@larsen.st
|
71
|
+
}, authors.keys.sort
|
72
|
+
end
|
73
|
+
|
74
|
+
should 'know the committers of the repository' do
|
75
|
+
committers = @repo.committers
|
76
|
+
assert_equal 29, committers.size
|
77
|
+
assert committers.values.all? { |committer| committer.is_a? Metior::Git::Actor }
|
78
|
+
|
79
|
+
assert_equal %w{
|
80
|
+
adam@therealadam.com aman@tmm1.net antonin@hildebrand.cz
|
81
|
+
bobbywilson0@gmail.com bryce@worldmedia.net chris@ozmm.org
|
82
|
+
davetron5000@gmail.com david.kowis@rackspace.com dustin@spy.net
|
83
|
+
engel@engel.uk.to evil@che.lu hiroshi3110@gmail.com
|
84
|
+
johan@johansorensen.com jos@catnook.com kamal.fariz@gmail.com
|
85
|
+
koraktor@gmail.com mtraverso@acm.org ohnobinki@ohnopublishing.net
|
86
|
+
paul+git@mjr.org pjhyett@gmail.com rsanheim@gmail.com
|
87
|
+
rtomayko@gmail.com schacon@gmail.com technoweenie@gmail.com
|
88
|
+
tim@dysinger.net tim@spork.in tom@mojombo.com tom@taco.(none)
|
89
|
+
voker57@gmail.com
|
90
|
+
}, committers.keys.sort
|
91
|
+
end
|
92
|
+
|
93
|
+
should 'know the top authors of the repository' do
|
94
|
+
authors = @repo.top_authors
|
95
|
+
assert_equal 3, authors.size
|
96
|
+
assert authors.all? { |author| author.is_a? Metior::Git::Actor }
|
97
|
+
|
98
|
+
assert_equal [
|
99
|
+
"tom@mojombo.com", "schacon@gmail.com", "technoweenie@gmail.com"
|
100
|
+
], authors.collect { |author| author.id }
|
101
|
+
end
|
102
|
+
|
103
|
+
should 'provide easy access to simple repository statistics' do
|
104
|
+
stats = Metior.simple_stats :git, File.dirname(File.dirname(__FILE__))
|
105
|
+
|
106
|
+
assert_equal 157, stats[:active_days].size
|
107
|
+
assert_equal 460, stats[:commit_count]
|
108
|
+
assert_in_delta 2.92993630573248, stats[:commits_per_active_day], 0.0001
|
109
|
+
assert_equal Time.at(1191997100), stats[:first_commit_date]
|
110
|
+
assert_equal Time.at(1306794294), stats[:last_commit_date]
|
111
|
+
assert_equal 5, stats[:top_contributors].size
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
22
116
|
end
|
data/test/test_github.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
#
|
4
4
|
# Copyright (c) 2011, Sebastian Staudt
|
5
5
|
|
6
|
+
require 'fixtures'
|
6
7
|
require 'helper'
|
7
8
|
|
8
9
|
class TestGitHub < Test::Unit::TestCase
|
@@ -17,27 +18,123 @@ class TestGitHub < Test::Unit::TestCase
|
|
17
18
|
assert_not Metior::GitHub.supports? :line_stats
|
18
19
|
end
|
19
20
|
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'A GitHub repository' do
|
24
|
+
|
25
|
+
setup do
|
26
|
+
@repo = Metior::GitHub::Repository.new 'mojombo', 'grit'
|
27
|
+
|
28
|
+
api_response = Fixtures.commits_as_rashies(''..'master')
|
29
|
+
@commits_stub = Octokit.stubs :commits
|
30
|
+
14.times { @commits_stub.returns api_response.shift(35) }
|
31
|
+
@commits_stub.then.raises Faraday::Error::ResourceNotFound.new(nil)
|
32
|
+
end
|
33
|
+
|
34
|
+
should 'be able to load all commits from the repository\'s default branch' do
|
35
|
+
commits = @repo.commits
|
36
|
+
assert_equal 460, commits.size
|
37
|
+
assert commits.all? { |commit| commit.is_a? Metior::GitHub::Commit }
|
38
|
+
|
39
|
+
head = commits.first
|
40
|
+
assert_equal '1b2fe77', head.id
|
41
|
+
end
|
42
|
+
|
43
|
+
should 'be able to load a range of commits from the repository' do
|
44
|
+
@commits_stub = Octokit.stubs :commits
|
45
|
+
api_response = Fixtures.commits_as_rashies(''..'4c592b4')
|
46
|
+
14.times { @commits_stub.returns api_response.shift(35) }
|
47
|
+
@commits_stub.raises Faraday::Error::ResourceNotFound.new(nil)
|
48
|
+
api_response = Fixtures.commits_as_rashies(''..'ef2870b')
|
49
|
+
13.times { @commits_stub.returns api_response.shift(35) }
|
50
|
+
@commits_stub.then.raises Faraday::Error::ResourceNotFound.new(nil)
|
51
|
+
|
52
|
+
commits = @repo.commits 'ef2870b'..'4c592b4'
|
53
|
+
assert_equal 6, commits.size
|
54
|
+
assert commits.all? { |commit| commit.is_a? Metior::GitHub::Commit }
|
55
|
+
assert_equal '4c592b4', commits.first.id
|
56
|
+
assert_equal 'f0cc7f7', commits.last.id
|
57
|
+
end
|
58
|
+
|
59
|
+
should 'know the authors of the repository' do
|
60
|
+
authors = @repo.authors
|
61
|
+
assert_equal 37, authors.size
|
62
|
+
assert authors.values.all? { |author| author.is_a? Metior::GitHub::Actor }
|
63
|
+
|
64
|
+
assert_equal %w{
|
65
|
+
adam@therealadam.com aman@tmm1.net antonin@hildebrand.cz
|
66
|
+
bobbywilson0@gmail.com bryce@worldmedia.net cehoffman@gmail.com
|
67
|
+
chapados@sciencegeeks.org cho45@lowreal.net chris@ozmm.org
|
68
|
+
davetron5000@gmail.com david.kowis@rackspace.com dustin@spy.net
|
69
|
+
engel@engel.uk.to evil@che.lu gram.gibson@uky.edu
|
70
|
+
hiroshi3110@gmail.com igor@wiedler.ch johan@johansorensen.com
|
71
|
+
jos@catnook.com jpriddle@nevercraft.net kamal.fariz@gmail.com
|
72
|
+
koraktor@gmail.com mtraverso@acm.org ohnobinki@ohnopublishing.net
|
73
|
+
paul+git@mjr.org pjhyett@gmail.com rsanheim@gmail.com
|
74
|
+
rtomayko@gmail.com schacon@gmail.com scott@railsnewbie.com
|
75
|
+
technoweenie@gmail.com tim@dysinger.net tim@spork.in
|
76
|
+
tom@mojombo.com tom@taco.(none) voker57@gmail.com wayne@larsen.st
|
77
|
+
}, authors.keys.sort
|
78
|
+
end
|
79
|
+
|
80
|
+
should 'know the committers of the repository' do
|
81
|
+
committers = @repo.committers
|
82
|
+
assert_equal 29, committers.size
|
83
|
+
assert committers.values.all? { |committer| committer.is_a? Metior::GitHub::Actor }
|
84
|
+
|
85
|
+
assert_equal %w{
|
86
|
+
adam@therealadam.com aman@tmm1.net antonin@hildebrand.cz
|
87
|
+
bobbywilson0@gmail.com bryce@worldmedia.net chris@ozmm.org
|
88
|
+
davetron5000@gmail.com david.kowis@rackspace.com dustin@spy.net
|
89
|
+
engel@engel.uk.to evil@che.lu hiroshi3110@gmail.com
|
90
|
+
johan@johansorensen.com jos@catnook.com kamal.fariz@gmail.com
|
91
|
+
koraktor@gmail.com mtraverso@acm.org ohnobinki@ohnopublishing.net
|
92
|
+
paul+git@mjr.org pjhyett@gmail.com rsanheim@gmail.com
|
93
|
+
rtomayko@gmail.com schacon@gmail.com technoweenie@gmail.com
|
94
|
+
tim@dysinger.net tim@spork.in tom@mojombo.com tom@taco.(none)
|
95
|
+
voker57@gmail.com
|
96
|
+
}, committers.keys.sort
|
97
|
+
end
|
98
|
+
|
99
|
+
should 'know the top authors of the repository' do
|
100
|
+
authors = @repo.top_authors
|
101
|
+
assert_equal 3, authors.size
|
102
|
+
assert authors.all? { |author| author.is_a? Metior::GitHub::Actor }
|
103
|
+
|
104
|
+
assert_equal [
|
105
|
+
"tom@mojombo.com", "schacon@gmail.com", "technoweenie@gmail.com"
|
106
|
+
], authors.collect { |author| author.id }
|
107
|
+
end
|
108
|
+
|
20
109
|
should 'not be able to get file stats of a repository' do
|
21
|
-
repo = Metior::GitHub::Repository.new 'koraktor', 'rubikon'
|
22
110
|
assert_raises UnsupportedError do
|
23
|
-
repo.file_stats
|
111
|
+
@repo.file_stats
|
24
112
|
end
|
25
113
|
end
|
26
114
|
|
27
115
|
should 'not be able to get the most significant authors of a repository' do
|
28
|
-
repo = Metior::GitHub::Repository.new 'koraktor', 'rubikon'
|
29
116
|
assert_raises UnsupportedError do
|
30
|
-
repo.significant_authors
|
117
|
+
@repo.significant_authors
|
31
118
|
end
|
32
119
|
end
|
33
120
|
|
34
121
|
should 'not be able to get the most significant commits of a repository' do
|
35
|
-
repo = Metior::GitHub::Repository.new 'koraktor', 'rubikon'
|
36
122
|
assert_raises UnsupportedError do
|
37
|
-
repo.significant_commits
|
123
|
+
@repo.significant_commits
|
38
124
|
end
|
39
125
|
end
|
40
126
|
|
127
|
+
should 'provide easy access to simple repository statistics' do
|
128
|
+
stats = Metior.simple_stats :github, 'mojombo', 'grit'
|
129
|
+
|
130
|
+
assert_equal 157, stats[:active_days].size
|
131
|
+
assert_equal 460, stats[:commit_count]
|
132
|
+
assert_in_delta 2.92993630573248, stats[:commits_per_active_day], 0.0001
|
133
|
+
assert_equal Time.at(1191997100), stats[:first_commit_date]
|
134
|
+
assert_equal Time.at(1306794294), stats[:last_commit_date]
|
135
|
+
assert_equal 5, stats[:top_contributors].size
|
136
|
+
end
|
137
|
+
|
41
138
|
end
|
42
139
|
|
43
140
|
end
|
data/test/test_repository.rb
CHANGED
@@ -43,108 +43,4 @@ class TestRepository < Test::Unit::TestCase
|
|
43
43
|
|
44
44
|
end
|
45
45
|
|
46
|
-
context 'A repository implementation' do
|
47
|
-
|
48
|
-
setup do
|
49
|
-
require 'mock_vcs/repository'
|
50
|
-
|
51
|
-
repo_file = "#{File.dirname(__FILE__)}/fixtures/mojombo-grit-master-1b2fe77.txt"
|
52
|
-
@repo = MockVCS::Repository.new repo_file
|
53
|
-
end
|
54
|
-
|
55
|
-
should 'be able to load all commits from the repository' do
|
56
|
-
commits = @repo.commits
|
57
|
-
assert_equal 415, commits.size
|
58
|
-
assert commits.all? { |commit| commit.is_a? Metior::Commit }
|
59
|
-
|
60
|
-
head = commits.first
|
61
|
-
assert_equal '4c592b4', head.id
|
62
|
-
end
|
63
|
-
|
64
|
-
should 'be able to load a range of commits from the repository' do
|
65
|
-
commits = @repo.commits 'ef2870b'..'4c592b4'
|
66
|
-
assert_equal 5, commits.size
|
67
|
-
assert commits.all? { |commit| commit.is_a? Metior::Commit }
|
68
|
-
assert_equal '4c592b4', commits.first.id
|
69
|
-
assert_equal 'f0cc7f7', commits.last.id
|
70
|
-
end
|
71
|
-
|
72
|
-
should 'know the authors of the repository' do
|
73
|
-
authors = @repo.authors
|
74
|
-
assert_equal 37, authors.size
|
75
|
-
assert authors.values.all? { |author| author.is_a? Metior::Actor }
|
76
|
-
|
77
|
-
assert_equal %w{
|
78
|
-
adam@therealadam.com aman@tmm1.net antonin@hildebrand.cz
|
79
|
-
bobbywilson0@gmail.com bryce@worldmedia.net cehoffman@gmail.com
|
80
|
-
chapados@sciencegeeks.org cho45@lowreal.net chris@ozmm.org
|
81
|
-
davetron5000@gmail.com david.kowis@rackspace.com dustin@spy.net
|
82
|
-
engel@engel.uk.to evil@che.lu gram.gibson@uky.edu
|
83
|
-
hiroshi3110@gmail.com igor@wiedler.ch johan@johansorensen.com
|
84
|
-
jos@catnook.com jpriddle@nevercraft.net kamal.fariz@gmail.com
|
85
|
-
koraktor@gmail.com mtraverso@acm.org ohnobinki@ohnopublishing.net
|
86
|
-
paul+git@mjr.org pjhyett@gmail.com rsanheim@gmail.com
|
87
|
-
rtomayko@gmail.com schacon@gmail.com scott@railsnewbie.com
|
88
|
-
technoweenie@gmail.com tim@dysinger.net tim@spork.in
|
89
|
-
tom@mojombo.com tom@taco.(none) voker57@gmail.com wayne@larsen.st
|
90
|
-
}, authors.keys.sort
|
91
|
-
end
|
92
|
-
|
93
|
-
should 'know the committers of the repository' do
|
94
|
-
committers = @repo.committers
|
95
|
-
assert_equal 29, committers.size
|
96
|
-
assert committers.values.all? { |committer| committer.is_a? Metior::Actor }
|
97
|
-
|
98
|
-
assert_equal %w{
|
99
|
-
adam@therealadam.com aman@tmm1.net antonin@hildebrand.cz
|
100
|
-
bobbywilson0@gmail.com bryce@worldmedia.net chris@ozmm.org
|
101
|
-
davetron5000@gmail.com david.kowis@rackspace.com dustin@spy.net
|
102
|
-
engel@engel.uk.to evil@che.lu hiroshi3110@gmail.com
|
103
|
-
johan@johansorensen.com jos@catnook.com kamal.fariz@gmail.com
|
104
|
-
koraktor@gmail.com mtraverso@acm.org ohnobinki@ohnopublishing.net
|
105
|
-
paul+git@mjr.org pjhyett@gmail.com rsanheim@gmail.com
|
106
|
-
rtomayko@gmail.com schacon@gmail.com technoweenie@gmail.com
|
107
|
-
tim@dysinger.net tim@spork.in tom@mojombo.com tom@taco.(none)
|
108
|
-
voker57@gmail.com
|
109
|
-
}, committers.keys.sort
|
110
|
-
end
|
111
|
-
|
112
|
-
should 'know the most significant authors of the repository' do
|
113
|
-
authors = @repo.significant_authors
|
114
|
-
assert_equal 3, authors.size
|
115
|
-
assert authors.all? { |author| author.is_a? Metior::Actor }
|
116
|
-
|
117
|
-
assert_equal [
|
118
|
-
"tom@mojombo.com", "schacon@gmail.com", "rtomayko@gmail.com"
|
119
|
-
], authors.collect { |author| author.id }
|
120
|
-
end
|
121
|
-
|
122
|
-
should 'know the most significant commits of the repository' do
|
123
|
-
commits = @repo.significant_commits('master', 8)
|
124
|
-
assert_equal 8, commits.size
|
125
|
-
assert commits.all? { |commit| commit.is_a? Metior::Commit }
|
126
|
-
|
127
|
-
assert_equal %w{
|
128
|
-
c0f0b4f 47ab25c f3a24ae 18ec70e 242253b c87612b 6bb41e4 4d9c7be
|
129
|
-
}, commits.collect { |commit| commit.id }
|
130
|
-
|
131
|
-
modifications = commits.first.modifications
|
132
|
-
commits[1..-1].each do |commit|
|
133
|
-
assert modifications >= commit.modifications
|
134
|
-
modifications = commit.modifications
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
should 'know the top authors of the repository' do
|
139
|
-
authors = @repo.top_authors
|
140
|
-
assert_equal 3, authors.size
|
141
|
-
assert authors.all? { |author| author.is_a? Metior::Actor }
|
142
|
-
|
143
|
-
assert_equal [
|
144
|
-
"tom@mojombo.com", "schacon@gmail.com", "technoweenie@gmail.com"
|
145
|
-
], authors.collect { |author| author.id }
|
146
|
-
end
|
147
|
-
|
148
|
-
end
|
149
|
-
|
150
46
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: metior
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 29
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 3
|
10
|
+
version: 0.1.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Sebastian Staudt
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-06-
|
18
|
+
date: 2011-06-13 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
type: :runtime
|
@@ -165,11 +165,9 @@ files:
|
|
165
165
|
- lib/metior/vcs.rb
|
166
166
|
- lib/metior/version.rb
|
167
167
|
- metior.gemspec
|
168
|
+
- test/fixtures.rb
|
168
169
|
- test/fixtures/mojombo-grit-master-1b2fe77.txt
|
169
170
|
- test/helper.rb
|
170
|
-
- test/mock_vcs/actor.rb
|
171
|
-
- test/mock_vcs/commit.rb
|
172
|
-
- test/mock_vcs/repository.rb
|
173
171
|
- test/test_class_loading.rb
|
174
172
|
- test/test_git.rb
|
175
173
|
- test/test_github.rb
|
@@ -210,11 +208,9 @@ signing_key:
|
|
210
208
|
specification_version: 3
|
211
209
|
summary: A source code history analyzer API
|
212
210
|
test_files:
|
211
|
+
- test/fixtures.rb
|
213
212
|
- test/fixtures/mojombo-grit-master-1b2fe77.txt
|
214
213
|
- test/helper.rb
|
215
|
-
- test/mock_vcs/actor.rb
|
216
|
-
- test/mock_vcs/commit.rb
|
217
|
-
- test/mock_vcs/repository.rb
|
218
214
|
- test/test_class_loading.rb
|
219
215
|
- test/test_git.rb
|
220
216
|
- test/test_github.rb
|
data/test/mock_vcs/actor.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
# This code is free software; you can redistribute it and/or modify it under
|
2
|
-
# the terms of the new BSD License.
|
3
|
-
#
|
4
|
-
# Copyright (c) 2011, Sebastian Staudt
|
5
|
-
|
6
|
-
require 'metior/actor'
|
7
|
-
|
8
|
-
module Metior
|
9
|
-
|
10
|
-
module MockVCS
|
11
|
-
|
12
|
-
class Actor < Metior::Actor
|
13
|
-
|
14
|
-
def self.id_for(actor)
|
15
|
-
actor.last
|
16
|
-
end
|
17
|
-
|
18
|
-
def initialize(repo, actor)
|
19
|
-
super repo
|
20
|
-
|
21
|
-
@id = actor.last
|
22
|
-
@name = actor.first
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
data/test/mock_vcs/commit.rb
DELETED
@@ -1,53 +0,0 @@
|
|
1
|
-
# This code is free software; you can redistribute it and/or modify it under
|
2
|
-
# the terms of the new BSD License.
|
3
|
-
#
|
4
|
-
# Copyright (c) 2011, Sebastian Staudt
|
5
|
-
|
6
|
-
require 'mock_vcs/actor'
|
7
|
-
require 'metior/commit'
|
8
|
-
|
9
|
-
module Metior
|
10
|
-
|
11
|
-
module MockVCS
|
12
|
-
|
13
|
-
class Commit < Metior::Commit
|
14
|
-
|
15
|
-
def initialize(repo, range, commit)
|
16
|
-
super repo, range
|
17
|
-
|
18
|
-
@additions = commit[:impact].first.to_i
|
19
|
-
@authored_date = Time.at commit[:info][6].to_i
|
20
|
-
@committed_date = Time.at commit[:info][3].to_i
|
21
|
-
@deletions = commit[:impact].last.to_i
|
22
|
-
@id = commit[:ids].first
|
23
|
-
@message = commit[:info].first
|
24
|
-
|
25
|
-
authors = repo.authors range
|
26
|
-
@author = authors[Actor.id_for commit[:info][4..5]]
|
27
|
-
@author = Actor.new repo, commit[:info][4..5] if author.nil?
|
28
|
-
@author.add_commit self
|
29
|
-
|
30
|
-
committers = repo.committers range
|
31
|
-
@committer = committers[Actor.id_for commit[:info][1..2]]
|
32
|
-
@committer = Actor.new repo, commit[:info][1..2] if @committer.nil?
|
33
|
-
@committer.add_commit self
|
34
|
-
|
35
|
-
@added_files = []
|
36
|
-
@modified_files = []
|
37
|
-
@deleted_files = []
|
38
|
-
commit[:files].each do |file|
|
39
|
-
if file.first == 'A'
|
40
|
-
@added_files << file.last
|
41
|
-
elsif file.first == 'A'
|
42
|
-
@deleted_files << file.last
|
43
|
-
else
|
44
|
-
@modified_files << file.last
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
end
|
50
|
-
|
51
|
-
end
|
52
|
-
|
53
|
-
end
|
data/test/mock_vcs/repository.rb
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
# This code is free software; you can redistribute it and/or modify it under
|
2
|
-
# the terms of the new BSD License.
|
3
|
-
#
|
4
|
-
# Copyright (c) 2011, Sebastian Staudt
|
5
|
-
|
6
|
-
require 'metior/repository'
|
7
|
-
require 'mock_vcs/commit'
|
8
|
-
|
9
|
-
module Metior
|
10
|
-
|
11
|
-
module MockVCS
|
12
|
-
|
13
|
-
NAME = :mock
|
14
|
-
|
15
|
-
include VCS
|
16
|
-
|
17
|
-
class Repository < Metior::Repository
|
18
|
-
|
19
|
-
DEFAULT_BRANCH = 'master'
|
20
|
-
|
21
|
-
include Metior::MockVCS
|
22
|
-
|
23
|
-
def initialize(path)
|
24
|
-
super path
|
25
|
-
|
26
|
-
@file = File.open(File.expand_path(path), 'r')
|
27
|
-
@file.set_encoding 'utf-8' if @file.respond_to? :set_encoding
|
28
|
-
end
|
29
|
-
|
30
|
-
def load_commits(range)
|
31
|
-
commits = []
|
32
|
-
|
33
|
-
commit = {}
|
34
|
-
@file.lines.each do |line|
|
35
|
-
line.strip!
|
36
|
-
|
37
|
-
next if line.empty?
|
38
|
-
|
39
|
-
if line.match /^[AMD]\0/
|
40
|
-
commit[:files] = [] unless commit.key? :files
|
41
|
-
commit[:files] << line.split("\0")
|
42
|
-
elsif line.match /\d+\0\d+$/
|
43
|
-
commit[:impact] = line.split("\0")
|
44
|
-
|
45
|
-
if commits.empty?
|
46
|
-
if range.first != '' && !commit[:ids].include?(range.last)
|
47
|
-
commit = {}
|
48
|
-
next
|
49
|
-
end
|
50
|
-
elsif commit[:ids].include? range.first
|
51
|
-
break
|
52
|
-
end
|
53
|
-
|
54
|
-
commits << commit
|
55
|
-
commit = {}
|
56
|
-
else
|
57
|
-
line = line.split("\0")
|
58
|
-
ids = [line[0]]
|
59
|
-
ids += line[1][2..-2].split(', ') unless line[1].empty?
|
60
|
-
commit[:ids] = ids
|
61
|
-
commit[:info] = line[2..-1]
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
commits
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
69
|
-
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|