twigg-gerrit 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.
- 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: []
|