twigg-gerrit 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/twigg-gerrit/command/gerrit.rb +64 -0
- data/lib/twigg-gerrit/gerrit/author.rb +83 -0
- data/lib/twigg-gerrit/gerrit/change.rb +34 -0
- data/lib/twigg-gerrit/gerrit/db.rb +36 -0
- data/lib/twigg-gerrit/gerrit/tag.rb +71 -0
- data/lib/twigg-gerrit/gerrit/version.rb +5 -0
- data/lib/twigg-gerrit/gerrit.rb +8 -0
- data/lib/twigg-gerrit.rb +10 -0
- metadata +109 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2ff29dfdbc080f961f71a24c20859f54626df8ce
|
4
|
+
data.tar.gz: 82cb20f98939bfa5661d10d92e0d96c45048090c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 089b2d2dfdd246cafc3da1d707ff3d091a9441d1554a8a787bca00c92ed80c0486648c084e4a0f3615408b397065a278440caadf80e3f958fff8b3423beb7d90
|
7
|
+
data.tar.gz: 9c17dc46598d22256d377366bb9258abc4fc9e41a3470a9eb936915c7fa8191e8ffb3729fb19a56fe68de6de3e9af95827b39126440a7d249912e7f304f05c90
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Twigg
|
2
|
+
class Command
|
3
|
+
# The "gerrit" subcommand can be used to conveniently initialize a set of
|
4
|
+
# repos and keep them up-to-date.
|
5
|
+
class Gerrit < GitHost
|
6
|
+
include Util
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def sub_subcommands
|
11
|
+
super + ['stats']
|
12
|
+
end
|
13
|
+
|
14
|
+
# Shows a list of open changes, ordered by last update date (descending).
|
15
|
+
def stats
|
16
|
+
changes = ::Twigg::Gerrit::Change.changes
|
17
|
+
|
18
|
+
puts "Open changes (#{changes.count})"
|
19
|
+
changes.map do |change|
|
20
|
+
puts " #%-6d %s [%s] %s" % [
|
21
|
+
change.change_id,
|
22
|
+
change.subject,
|
23
|
+
change.full_name,
|
24
|
+
age(change.last_updated_on),
|
25
|
+
]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns a Gerrit address.
|
30
|
+
#
|
31
|
+
# Examples:
|
32
|
+
#
|
33
|
+
# address('foo')
|
34
|
+
# => ssh://jimmy@gerrit.example.com:29418/foo.git
|
35
|
+
# address(port: false, protocol: false)
|
36
|
+
# => jimmy@gerrit.example.com
|
37
|
+
#
|
38
|
+
def address(project = nil, port: true, protocol: true)
|
39
|
+
[].tap do |address|
|
40
|
+
address << 'ssh://' if protocol
|
41
|
+
address << "#{Config.gerrit.user}@#{Config.gerrit.host}"
|
42
|
+
address << ":#{Config.gerrit.port}" if port
|
43
|
+
address << "/#{project}.git" if project
|
44
|
+
end.join
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns the list of all projects hosted within a Gerrit instance.
|
48
|
+
def projects
|
49
|
+
@projects ||= begin
|
50
|
+
port = Config.gerrit.port.to_s
|
51
|
+
user_at_host = address(port: false, protocol: false)
|
52
|
+
command = ['ssh', '-p', port, user_at_host, 'gerrit', 'ls-projects']
|
53
|
+
|
54
|
+
# Don't bother redirecting stderr; let it slip through to the user,
|
55
|
+
# where it may provide useful feedback (such as "Permission denied
|
56
|
+
# (publickey)." or similar).
|
57
|
+
IO.popen(command, 'r') { |io| io.read }.split.tap do
|
58
|
+
die 'failed to retrieve project list' unless $?.success?
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Twigg
|
2
|
+
module Gerrit
|
3
|
+
# Author-centric stats for activity on Gerrit (commenting, reviewing) and
|
4
|
+
# "quality" (attracting comments, pushing multiple patch sets).
|
5
|
+
class Author
|
6
|
+
class << self
|
7
|
+
# Returns a Hash of stats where the keys are author names and the
|
8
|
+
# values are hashes containing stats (keys: stat labels, values:
|
9
|
+
# counts).
|
10
|
+
def stats(days: 7)
|
11
|
+
Hash.new { |h, k| h[k] = {} }.tap do |hash|
|
12
|
+
{
|
13
|
+
comments_posted: comments_posted(days),
|
14
|
+
comments_received: comments_received(days),
|
15
|
+
recently_active_changes: recently_active_changes(days),
|
16
|
+
revisions_pushed: revisions_pushed(days),
|
17
|
+
scores_assigned: scores_assigned(days),
|
18
|
+
}.each do |label, stats|
|
19
|
+
stats.each do |author_stats|
|
20
|
+
hash[author_stats[:full_name]][label] = author_stats[:count]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def comments_posted(days)
|
29
|
+
DB[:patch_comments].
|
30
|
+
select_group(:full_name).
|
31
|
+
select_append { count(1).as(:count) }.
|
32
|
+
join(:accounts, account_id: :author_id).
|
33
|
+
where('written_on > DATE_SUB(NOW(), INTERVAL ? DAY)', days).
|
34
|
+
order(Sequel.desc(:count)).
|
35
|
+
all
|
36
|
+
end
|
37
|
+
|
38
|
+
def scores_assigned(days)
|
39
|
+
DB[:change_messages].
|
40
|
+
select_group(:full_name).
|
41
|
+
select_append { count(1).as(:count) }.
|
42
|
+
join(:accounts, account_id: :author_id).
|
43
|
+
where('written_on > DATE_SUB(NOW(), INTERVAL ? DAY)', days).
|
44
|
+
order(Sequel.desc(:count)).
|
45
|
+
all
|
46
|
+
end
|
47
|
+
|
48
|
+
def revisions_pushed(days)
|
49
|
+
DB[:patch_sets].
|
50
|
+
select_group(:full_name).
|
51
|
+
select_append { count(1).as(:count) }.
|
52
|
+
join(:changes, change_id: :change_id).
|
53
|
+
join(:accounts, account_id: :owner_account_id).
|
54
|
+
where('last_updated_on > DATE_SUB(NOW(), INTERVAL ? DAY)', days).
|
55
|
+
order(Sequel.desc(:count)).
|
56
|
+
all
|
57
|
+
end
|
58
|
+
|
59
|
+
def comments_received(days)
|
60
|
+
DB[:patch_comments].
|
61
|
+
select_group(:full_name).
|
62
|
+
select_append { count(1).as(:count) }.
|
63
|
+
join(:changes, change_id: :change_id).
|
64
|
+
join(:accounts, account_id: :owner_account_id).
|
65
|
+
where('last_updated_on > DATE_SUB(NOW(), INTERVAL ? DAY)', days).
|
66
|
+
where('author_id != owner_account_id').
|
67
|
+
order(Sequel.desc(:count)).
|
68
|
+
all
|
69
|
+
end
|
70
|
+
|
71
|
+
def recently_active_changes(days)
|
72
|
+
DB[:changes].
|
73
|
+
select_group(:full_name).
|
74
|
+
select_append { count(1).as(:count) }.
|
75
|
+
join(:accounts, account_id: :owner_account_id).
|
76
|
+
where('last_updated_on > DATE_SUB(NOW(), INTERVAL ? DAY)', days).
|
77
|
+
order(Sequel.desc(:count)).
|
78
|
+
all
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Twigg
|
2
|
+
module Gerrit
|
3
|
+
class Change
|
4
|
+
class << self
|
5
|
+
def changes
|
6
|
+
DB[:changes].
|
7
|
+
select(:change_id, :last_updated_on, :subject, :full_name).
|
8
|
+
join(:accounts, account_id: :owner_account_id).
|
9
|
+
where(status: 'n').
|
10
|
+
order(Sequel.desc(:last_updated_on)).
|
11
|
+
all.map do |change|
|
12
|
+
new(change_id: change[:change_id],
|
13
|
+
subject: change[:subject],
|
14
|
+
full_name: change[:full_name],
|
15
|
+
last_updated_on: change[:last_updated_on])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :change_id, :subject, :full_name, :last_updated_on
|
21
|
+
|
22
|
+
def initialize(options = {})
|
23
|
+
raise ArgumentError unless @change_id = options[:change_id]
|
24
|
+
raise ArgumentError unless @subject = options[:subject]
|
25
|
+
raise ArgumentError unless @full_name = options[:full_name]
|
26
|
+
raise ArgumentError unless @last_updated_on = options[:last_updated_on]
|
27
|
+
end
|
28
|
+
|
29
|
+
def url
|
30
|
+
Config.gerrit.web.host + '/' + change_id.to_s
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'sequel'
|
3
|
+
|
4
|
+
module Twigg
|
5
|
+
module Gerrit
|
6
|
+
class DB
|
7
|
+
include Dependency # for with_dependency
|
8
|
+
|
9
|
+
class << self
|
10
|
+
extend Forwardable
|
11
|
+
def_delegators :db, :[]
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def db
|
16
|
+
@db ||= new
|
17
|
+
@db.db
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def db
|
22
|
+
@db ||= begin
|
23
|
+
adapter = Config.gerrit.db.adapter # eg. mysql2
|
24
|
+
|
25
|
+
with_dependency(adapter) do
|
26
|
+
db = Sequel.send(adapter, Config.gerrit.db.database,
|
27
|
+
host: Config.gerrit.db.host,
|
28
|
+
password: Config.gerrit.db.password,
|
29
|
+
port: Config.gerrit.db.port,
|
30
|
+
user: Config.gerrit.db.user)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Twigg
|
2
|
+
module Gerrit
|
3
|
+
# Tag-related stats.
|
4
|
+
class Tag
|
5
|
+
class << self
|
6
|
+
def stats(days: 7)
|
7
|
+
# TODO: produce per author (to/from) and global stats
|
8
|
+
(change_messages(days) + comment_messages(days)).each do |result|
|
9
|
+
tags = tags_from_result(result)
|
10
|
+
=begin
|
11
|
+
{
|
12
|
+
greg: {
|
13
|
+
given: {
|
14
|
+
tag: count
|
15
|
+
},
|
16
|
+
received: {
|
17
|
+
tag: count
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
// global stats
|
22
|
+
nil: {
|
23
|
+
tag: count
|
24
|
+
}
|
25
|
+
=end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def comment_messages(days)
|
32
|
+
DB[<<-SQL, days].all
|
33
|
+
SELECT message,
|
34
|
+
from_accounts.full_name AS from_full_name,
|
35
|
+
to_accounts.full_name AS to_full_name
|
36
|
+
FROM patch_comments
|
37
|
+
JOIN accounts AS from_accounts
|
38
|
+
ON patch_comments.author_id = from_accounts.account_id
|
39
|
+
JOIN changes
|
40
|
+
ON patch_comments.change_id = changes.change_id
|
41
|
+
JOIN accounts AS to_accounts
|
42
|
+
ON changes.owner_account_id = to_accounts.account_id
|
43
|
+
WHERE written_on > DATE_SUB(NOW(), INTERVAL ? DAY)
|
44
|
+
AND message like '%@%'
|
45
|
+
SQL
|
46
|
+
end
|
47
|
+
|
48
|
+
def change_messages(days)
|
49
|
+
DB[<<-SQL, days].all
|
50
|
+
SELECT message,
|
51
|
+
from_accounts.full_name AS from_full_name,
|
52
|
+
to_accounts.full_name AS to_full_name
|
53
|
+
FROM change_messages
|
54
|
+
JOIN accounts AS from_accounts
|
55
|
+
ON change_messages.author_id = from_accounts.account_id
|
56
|
+
JOIN changes
|
57
|
+
ON change_messages.change_id = changes.change_id
|
58
|
+
JOIN accounts AS to_accounts
|
59
|
+
ON changes.owner_account_id = to_accounts.account_id
|
60
|
+
WHERE written_on > DATE_SUB(NOW(), INTERVAL ? DAY)
|
61
|
+
AND message like '%@%'
|
62
|
+
SQL
|
63
|
+
end
|
64
|
+
|
65
|
+
def tags_from_result(result)
|
66
|
+
result[:message].scan(/(?<=@)\w+/).map(&:downcase)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/twigg-gerrit.rb
ADDED
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: twigg-gerrit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Causes Engineering
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-08-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sequel
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: twigg
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.0.1
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.0.1
|
69
|
+
description: Twigg provides stats for activity in Git repositories. This is the adapter
|
70
|
+
that enables Twigg to work with Gerrit installations.
|
71
|
+
email:
|
72
|
+
- eng@causes.com
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- lib/twigg-gerrit/command/gerrit.rb
|
78
|
+
- lib/twigg-gerrit/gerrit/author.rb
|
79
|
+
- lib/twigg-gerrit/gerrit/change.rb
|
80
|
+
- lib/twigg-gerrit/gerrit/db.rb
|
81
|
+
- lib/twigg-gerrit/gerrit/tag.rb
|
82
|
+
- lib/twigg-gerrit/gerrit/version.rb
|
83
|
+
- lib/twigg-gerrit/gerrit.rb
|
84
|
+
- lib/twigg-gerrit.rb
|
85
|
+
homepage: https://github.com/causes/twigg
|
86
|
+
licenses:
|
87
|
+
- MIT
|
88
|
+
metadata: {}
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - '>='
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: 2.0.0
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
requirements: []
|
104
|
+
rubyforge_project:
|
105
|
+
rubygems_version: 2.0.3
|
106
|
+
signing_key:
|
107
|
+
specification_version: 4
|
108
|
+
summary: Gerrit adapter for Twigg repo statistics tool
|
109
|
+
test_files: []
|