twigg-gerrit 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,5 @@
1
+ module Twigg
2
+ module Gerrit
3
+ VERSION = '0.0.1'
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ module Twigg
2
+ module Gerrit
3
+ autoload :VERSION, 'twigg-gerrit/gerrit/version'
4
+ autoload :Author, 'twigg-gerrit/gerrit/author'
5
+ autoload :Change, 'twigg-gerrit/gerrit/change'
6
+ autoload :DB, 'twigg-gerrit/gerrit/db'
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ require 'twigg'
2
+ require 'twigg/command'
3
+
4
+ module Twigg
5
+ autoload :Gerrit, 'twigg-gerrit/gerrit'
6
+
7
+ class Command
8
+ autoload :Gerrit, 'twigg-gerrit/command/gerrit'
9
+ end
10
+ end
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: []