github_org_reports 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -3,7 +3,7 @@ source "http://rubygems.org"
3
3
  # Example:
4
4
  # gem "activesupport", ">= 2.3.5"
5
5
 
6
- gem "baza", :path => "/Users/kaspernj/Dev/Ruby/baza"
6
+ gem "baza", ">= 0.0.10", :path => "/Users/kaspernj/Dev/Ruby/baza"
7
7
  gem "json"
8
8
  gem "github_api"
9
9
  gem "string-cases"
@@ -1,10 +1,11 @@
1
1
  PATH
2
2
  remote: /Users/kaspernj/Dev/Ruby/baza
3
3
  specs:
4
- baza (0.0.8)
4
+ baza (0.0.10)
5
5
  array_enumerator
6
6
  datet
7
7
  knjrbfw
8
+ string-cases
8
9
  wref
9
10
 
10
11
  GEM
@@ -80,7 +81,7 @@ PLATFORMS
80
81
  ruby
81
82
 
82
83
  DEPENDENCIES
83
- baza!
84
+ baza (>= 0.0.10)!
84
85
  bundler (>= 1.0.0)
85
86
  github_api
86
87
  jeweler (~> 1.8.4)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0
1
+ 0.0.1
@@ -0,0 +1,84 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "github_org_reports"
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["kaspernj"]
12
+ s.date = "2013-05-16"
13
+ s.description = "A gem to generate organization reports based on pull requests and commits."
14
+ s.email = "k@spernj.org"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rspec",
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "LICENSE.txt",
25
+ "README.rdoc",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "github_org_reports.gemspec",
29
+ "include/github_org_reports_dbschema.rb",
30
+ "include/github_org_reports_models.rb",
31
+ "include/github_org_reports_repo.rb",
32
+ "lib/github_org_reports.rb",
33
+ "models/commit.rb",
34
+ "models/commit_organization_link.rb",
35
+ "models/organization.rb",
36
+ "models/pull_request.rb",
37
+ "models/pull_request_organization_link.rb",
38
+ "models/user.rb",
39
+ "spec/github_org_reports_spec.rb",
40
+ "spec/spec_helper.rb"
41
+ ]
42
+ s.homepage = "http://github.com/kaspernj/github_org_reports"
43
+ s.licenses = ["MIT"]
44
+ s.require_paths = ["lib"]
45
+ s.rubygems_version = "1.8.23"
46
+ s.summary = "A gem to generate organization reports based on pull requests and commits."
47
+
48
+ if s.respond_to? :specification_version then
49
+ s.specification_version = 3
50
+
51
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
52
+ s.add_runtime_dependency(%q<baza>, [">= 0.0.10"])
53
+ s.add_runtime_dependency(%q<json>, [">= 0"])
54
+ s.add_runtime_dependency(%q<github_api>, [">= 0"])
55
+ s.add_runtime_dependency(%q<string-cases>, [">= 0"])
56
+ s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
57
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
58
+ s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
59
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
60
+ s.add_development_dependency(%q<sqlite3>, [">= 0"])
61
+ else
62
+ s.add_dependency(%q<baza>, [">= 0.0.10"])
63
+ s.add_dependency(%q<json>, [">= 0"])
64
+ s.add_dependency(%q<github_api>, [">= 0"])
65
+ s.add_dependency(%q<string-cases>, [">= 0"])
66
+ s.add_dependency(%q<rspec>, ["~> 2.8.0"])
67
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
68
+ s.add_dependency(%q<bundler>, [">= 1.0.0"])
69
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
70
+ s.add_dependency(%q<sqlite3>, [">= 0"])
71
+ end
72
+ else
73
+ s.add_dependency(%q<baza>, [">= 0.0.10"])
74
+ s.add_dependency(%q<json>, [">= 0"])
75
+ s.add_dependency(%q<github_api>, [">= 0"])
76
+ s.add_dependency(%q<string-cases>, [">= 0"])
77
+ s.add_dependency(%q<rspec>, ["~> 2.8.0"])
78
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
79
+ s.add_dependency(%q<bundler>, [">= 1.0.0"])
80
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
81
+ s.add_dependency(%q<sqlite3>, [">= 0"])
82
+ end
83
+ end
84
+
@@ -4,6 +4,8 @@ class GithubOrgReports::Dbschema
4
4
  :Commit => {
5
5
  :columns => [
6
6
  {:name => :id, :type => :int, :autoincr => true, :primarykey => true},
7
+ {:name => :repository_name, :type => :varchar},
8
+ {:name => :repository_user, :type => :varchar},
7
9
  {:name => :user_id, :type => :int},
8
10
  {:name => :pull_request_id, :type => :int},
9
11
  {:name => :sha, :type => :varchar},
@@ -12,6 +14,8 @@ class GithubOrgReports::Dbschema
12
14
  {:name => :time, :type => :int}
13
15
  ],
14
16
  :indexes => [
17
+ :repository_name,
18
+ :repository_user,
15
19
  :user_id
16
20
  ]
17
21
  },
@@ -43,15 +47,23 @@ class GithubOrgReports::Dbschema
43
47
  :PullRequest => {
44
48
  :columns => [
45
49
  {:name => :id, :type => :int, :autoincr => true, :primarykey => true},
50
+ {:name => :repository_name, :type => :varchar},
51
+ {:name => :repository_user, :type => :varchar},
46
52
  {:name => :github_id, :type => :int, :renames => [:pull_request_id]},
53
+ {:name => :number, :type => :int},
47
54
  {:name => :user_id, :type => :int},
55
+ {:name => :date, :type => :datetime},
56
+ {:name => :title, :type => :varchar},
48
57
  {:name => :text, :type => :text},
49
58
  {:name => :html, :type => :text},
50
59
  {:name => :time, :type => :int}
51
60
  ],
52
61
  :indexes => [
62
+ :repository_name,
63
+ :repository_user,
53
64
  :github_id,
54
- :user_id
65
+ :user_id,
66
+ :number
55
67
  ]
56
68
  },
57
69
  :PullRequestOrganizationLink => {
@@ -4,4 +4,12 @@ class GithubOrgReports::Repo
4
4
  def initialize(args)
5
5
  @args = args
6
6
  end
7
+
8
+ def name
9
+ return @args[:name]
10
+ end
11
+
12
+ def user
13
+ return @args[:user]
14
+ end
7
15
  end
@@ -11,6 +11,18 @@ class GithubOrgReports
11
11
  return GithubOrgReports.const_get(name)
12
12
  end
13
13
 
14
+ def self.secs_to_time(secs)
15
+ return "0:00" if secs <= 0
16
+
17
+ hours = (secs / 3600).floor
18
+ secs -= hours * 3600
19
+
20
+ mins = (secs / 60).floor
21
+ secs -= mins * 60
22
+
23
+ return "#{hours}:#{sprintf("%02d", mins)}"
24
+ end
25
+
14
26
  def initialize(args = {})
15
27
  @args = args
16
28
  @repos = []
@@ -34,49 +46,93 @@ class GithubOrgReports
34
46
  @repos << repo
35
47
  end
36
48
 
37
- def scan_hash(str)
49
+ def self.scan_hash(str)
38
50
  str.to_s.scan(/!(\{(.+?)\})!/) do |match|
51
+ json_str = match[0]
52
+
53
+
54
+ #Fix missing quotes in 'time' and 'orgs' to make it easier to write.
55
+ json_str.gsub!(/time:\s*([\d+:]+)/, "\"time\": \"\\1\"")
56
+
57
+ if orgs_match = json_str.match(/orgs:\s*\[(.+?)\]/)
58
+ orgs_str = orgs_match[1]
59
+ orgs_str.gsub!(/\s*(^|\s*,\s*)([A-z_\d]+)/, "\\1\"\\2\"")
60
+ json_str.gsub!(orgs_match[0], "\"orgs\": [#{orgs_str}]")
61
+ end
62
+
63
+
64
+ #Parse the JSON and yield it.
39
65
  begin
40
- yield JSON.parse(match[1])
66
+ yield JSON.parse(json_str)
41
67
  rescue JSON::ParserError => e
42
68
  $stderr.puts e.inspect
43
- $stderr.puts e.backtrace
69
+ #$stderr.puts e.backtrace
44
70
  end
45
71
  end
46
72
  end
47
73
 
48
74
  def scan
49
75
  @repos.each do |repo|
50
- gh_args = {}
51
- gh_args[:login] = repo.args[:login] if repo.args[:login]
52
- gh_args[:password] = repo.args[:password] if repo.args[:password]
76
+ @cur_repo = repo
77
+
78
+ gh_args = {
79
+ :user => repo.user,
80
+ :repo => repo.name
81
+ }
82
+ gh_args[:login] = repo.args[:login] unless repo.args[:login].to_s.strip.empty?
83
+ gh_args[:password] = repo.args[:password] unless repo.args[:password].to_s.strip.empty?
53
84
 
54
85
  gh = ::Github.new(gh_args)
55
86
 
56
- commits = gh.repos.commits.all(repo.args[:user], repo.args[:name])
87
+ commits = gh.repos.commits.all(gh_args)
57
88
  commits.each do |commit_data|
58
89
  commit = init_commit_from_data(commit_data)
59
90
  end
60
91
 
61
- prs = gh.pull_requests.list(repo.args[:user], repo.args[:name])
92
+ prs = []
93
+ gh.pull_requests.list(gh_args.merge(:state => "closed")).each do |pr|
94
+ prs << pr
95
+ end
96
+
97
+ gh.pull_requests.list(gh_args.merge(:state => "open")).each do |pr|
98
+ prs << pr
99
+ end
100
+
62
101
  prs.each do |pr_data|
63
102
  text = pr_data.body_text
64
103
 
104
+ name = pr_data.user.login
105
+ raise "Invalid name: '#{name}' (#{pr_data.to_hash})." if !name.is_a?(String)
65
106
  user = @ob.get_or_add(:User, {
66
- :name => pr_data.user
107
+ :name => name
67
108
  })
68
109
 
110
+
111
+ #puts "PullRequest: #{pr_data.to_hash}"
112
+ github_id = pr_data.id.to_i
113
+ raise "Invalid github-ID: '#{github_id}'." if github_id <= 0
114
+
115
+ number = pr_data.number.to_i
116
+ raise "Invalid number: '#{number}'." if number <= 0
117
+
69
118
  pr = @ob.get_or_add(:PullRequest, {
70
- :github_id => pr_data.id
119
+ :repository_user => @cur_repo.user,
120
+ :repository_name => @cur_repo.name,
121
+ :github_id => github_id,
122
+ :number => number
71
123
  })
72
124
 
125
+ #puts "PullRequest: #{pr_data.to_hash}"
126
+
73
127
  pr[:user_id] = user.id
128
+ pr[:title] = pr_data.title
74
129
  pr[:text] = pr_data.body_text
75
130
  pr[:html] = pr_data.body_html
131
+ pr[:date] = Time.parse(pr_data.created_at)
76
132
 
77
133
  pr.scan
78
134
 
79
- commits = gh.pull_requests.commits(:repo => repo.args[:name], :user => repo.args[:user], :number => pr_data.number)
135
+ commits = gh.pull_requests.commits(gh_args.merge(:number => pr_data.number))
80
136
  commits.each do |commit_data|
81
137
  commit = init_commit_from_data(commit_data)
82
138
  commit[:pull_request_id] = pr.id
@@ -88,34 +144,31 @@ class GithubOrgReports
88
144
  def scan_for_time_and_orgs(str)
89
145
  res = {:secs => 0, :orgs => [], :orgs_time => {}}
90
146
 
91
- self.scan_hash(str) do |hash|
147
+ GithubOrgReports.scan_hash(str) do |hash|
92
148
  #Parse time.
93
149
  if hash["time"] and match_time = hash["time"].to_s.match(/^(\d{1,2}):(\d{1,2})$/)
94
150
  secs = 0
95
151
  secs += match_time[1].to_i * 3600
96
152
  secs += match_time[2].to_i * 60
97
153
 
98
- res[:secs] += secs
99
-
100
154
  #Parse organizations.
101
155
  if orgs = hash["orgs"]
102
- orgs = [orgs] if !orgs.is_a?(Hash)
156
+ orgs = [orgs] if !orgs.is_a?(Array)
103
157
  orgs.each do |org_name_short|
104
158
  org_name_short_dc = org_name_short.to_s.downcase
105
159
  next if org_name_short_dc.strip.empty?
106
160
 
107
- org = self.ob.get_or_add(:Organization, {:name_short => org_name_short_dc})
161
+ raise "Invalid short-name: '#{org_name_short_dc}'." unless org_name_short_dc.match(/^[A-z\d+_]+$/)
108
162
 
109
- link = self.ob.get_or_add(:PullRequestOrganizationLink, {
110
- :organization_id => org.id,
111
- :pull_request_id => self.id
112
- })
163
+ org = self.ob.get_or_add(:Organization, {:name_short => org_name_short_dc})
113
164
 
114
165
  res[:orgs] << org unless res[:orgs].include?(org)
115
166
 
116
- res[:orgs_time][org.id] = {:secs => 0} unless res[:orgs].key?(org.id)
117
- res[:orgs_time][org.id][:secs] += match_time
167
+ res[:orgs_time][org.id] = {:secs => 0} unless res[:orgs_time].key?(org.id)
168
+ res[:orgs_time][org.id][:secs] += secs
118
169
  end
170
+ else
171
+ res[:secs] += secs
119
172
  end
120
173
  end
121
174
  end
@@ -126,11 +179,25 @@ class GithubOrgReports
126
179
  private
127
180
 
128
181
  def init_commit_from_data(commit_data)
182
+ sha = commit_data.sha
183
+ raise "Invalid SHA: '#{sha}' (#{commit_data.to_hash})." if sha.to_s.strip.empty?
184
+
129
185
  commit = @ob.get_or_add(:Commit, {
130
- :sha => commit_data.sha
186
+ :repository_user => @cur_repo.user,
187
+ :repository_name => @cur_repo.name,
188
+ :sha => sha
131
189
  })
132
- commit[:text] = commit_data.commit
133
- commit[:date] = commit_data.commit.date
190
+ raise "Commit didnt get added right '#{commit[:sha]}', '#{sha}'." if sha != commit[:sha]
191
+
192
+ text = commit_data.commit.message
193
+ raise "Invalid text: '#{text}' (#{commit_data.to_hash})." if !text.is_a?(String)
194
+ commit[:text] = text
195
+
196
+
197
+ date = Time.parse(commit_data.commit.committer.date)
198
+ raise "Invalid date: '#{date}' (#{commit_data.commit.to_hash})" if !date
199
+
200
+ commit[:date] = date
134
201
 
135
202
  if commit_data.author
136
203
  user = @ob.get_or_add(:User, {
@@ -1,6 +1,9 @@
1
1
  class GithubOrgReports::Models::Commit < Baza::Model
2
2
  has_one :User
3
3
  has_one :PullRequest
4
+ has_many [
5
+ [:CommitOrganizationLink, :commit_id]
6
+ ]
4
7
 
5
8
  def scan
6
9
  hash = ob.data[:github_org_reports].scan_for_time_and_orgs(self[:text])
@@ -10,9 +13,10 @@ class GithubOrgReports::Models::Commit < Baza::Model
10
13
  hash[:orgs].each do |org|
11
14
  link = self.ob.get_or_add(:CommitOrganizationLink, {
12
15
  :organization_id => org.id,
13
- :pull_request_id => self.id,
14
- :time => hash[:orgs_time][org.id]
16
+ :commit_id => self.id
15
17
  })
18
+
19
+ link[:time] = hash[:orgs_time][org.id][:secs]
16
20
  end
17
21
 
18
22
 
@@ -1,3 +1,9 @@
1
1
  class GithubOrgReports::Models::Organization < Baza::Model
2
-
2
+ def name
3
+ name_str = self[:name].to_s.strip
4
+ name_str = self[:name_short].to_s.strip if name_str.empty?
5
+ name_str = "[no name]" if name_str.empty?
6
+
7
+ return name_str
8
+ end
3
9
  end
@@ -1,5 +1,8 @@
1
1
  class GithubOrgReports::Models::PullRequest < Baza::Model
2
- has_many [[:PullRequestOrganizationLink, :pull_request_id]]
2
+ has_many [
3
+ [:PullRequestOrganizationLink, :pull_request_id],
4
+ [:Commit, :pull_request_id]
5
+ ]
3
6
 
4
7
  def scan
5
8
  hash = ob.data[:github_org_reports].scan_for_time_and_orgs(self[:text])
@@ -10,8 +13,9 @@ class GithubOrgReports::Models::PullRequest < Baza::Model
10
13
  link = self.ob.get_or_add(:PullRequestOrganizationLink, {
11
14
  :organization_id => org.id,
12
15
  :pull_request_id => self.id,
13
- :time => hash[:orgs_time][:secs]
14
16
  })
17
+
18
+ link[:time] = hash[:orgs_time][org.id][:secs]
15
19
  end
16
20
 
17
21
 
@@ -22,9 +26,46 @@ class GithubOrgReports::Models::PullRequest < Baza::Model
22
26
  return nil
23
27
  end
24
28
 
25
- def total_time_for_orgs(args)
26
- orgs = {}
29
+ def total_time_for_org(args)
30
+ org = args[:org]
31
+ raise "No ':org' was given." if !org
27
32
 
28
33
 
34
+ #Collect shared time.
35
+ secs = self[:time].to_i
36
+
37
+
38
+ #Collect time for the pull-request-organization-links.
39
+ self.pull_request_organization_links(:organization_id => org.id) do |prol|
40
+ secs += prol[:time].to_i
41
+ end
42
+
43
+
44
+ #Collect time from commits.
45
+ self.commits do |commit|
46
+ secs += commit[:time].to_i
47
+
48
+ commit.commit_organization_links(:organization_id => org.id) do |col|
49
+ secs += col[:time].to_i
50
+ end
51
+ end
52
+
53
+
54
+ return secs
55
+ end
56
+
57
+ def title(args = nil)
58
+ title_str = self[:title].to_s.strip
59
+ title_str = self[:text].to_s.lines.first.to_s.strip if title_str.empty?
60
+ mlength = (args && args[:maxlength]) ? args[:maxlength] : 15
61
+
62
+ if title_str.length > mlength
63
+ title_str = title_str.slice(0, mlength).strip
64
+ title_str << "..."
65
+ end
66
+
67
+ title_str = "[no title]" if title_str.empty?
68
+
69
+ return title_str
29
70
  end
30
71
  end
@@ -22,4 +22,35 @@ describe "GithubOrgReports" do
22
22
  raise e
23
23
  end
24
24
  end
25
+
26
+ it "should be able to parse special json strings" do
27
+ str = "!{time: 00:30, orgs: [knjit, gfish]}!\n"
28
+ str << "!{time: 00:15, orgs: [knjit]}!"
29
+
30
+ db_path = "#{Dir.tmpdir}/github_org_reports.sqlite3"
31
+ db = Baza::Db.new(:type => :sqlite3, :path => db_path, :index_append_table_name => true)
32
+
33
+ login_info = JSON.parse(File.read("#{File.dirname(__FILE__)}/spec_info.txt").to_s.strip)
34
+
35
+ begin
36
+ gor = GithubOrgReports.new(:db => db)
37
+
38
+ res = gor.scan_for_time_and_orgs(str)
39
+
40
+ org_knjit = gor.ob.get_by(:Organization, :name_short => "knjit")
41
+ org_gfish = gor.ob.get_by(:Organization, :name_short => "gfish")
42
+
43
+ res[:orgs_time][org_knjit.id][:secs].should eql(2700)
44
+ res[:orgs_time][org_gfish.id][:secs].should eql(1800)
45
+ rescue => e
46
+ puts e.inspect
47
+ puts e.backtrace
48
+ raise e
49
+ end
50
+ end
51
+
52
+ it "should be able to convert seconds to time strings" do
53
+ GithubOrgReports.secs_to_time(1800).should eql("0:30")
54
+ GithubOrgReports.secs_to_time(2700).should eql("0:45")
55
+ end
25
56
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: github_org_reports
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.0
5
+ version: 0.0.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - kaspernj
@@ -17,7 +17,7 @@ dependencies:
17
17
  requirements:
18
18
  - - ! '>='
19
19
  - !ruby/object:Gem::Version
20
- version: '0'
20
+ version: 0.0.10
21
21
  name: baza
22
22
  type: :runtime
23
23
  prerelease: false
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
- version: '0'
29
+ version: 0.0.10
30
30
  - !ruby/object:Gem::Dependency
31
31
  version_requirements: !ruby/object:Gem::Requirement
32
32
  none: false
@@ -171,6 +171,7 @@ files:
171
171
  - README.rdoc
172
172
  - Rakefile
173
173
  - VERSION
174
+ - github_org_reports.gemspec
174
175
  - include/github_org_reports_dbschema.rb
175
176
  - include/github_org_reports_models.rb
176
177
  - include/github_org_reports_repo.rb
@@ -197,7 +198,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
197
198
  - !ruby/object:Gem::Version
198
199
  segments:
199
200
  - 0
200
- hash: 2843595140910669046
201
+ hash: 241850806835355267
201
202
  version: '0'
202
203
  required_rubygems_version: !ruby/object:Gem::Requirement
203
204
  none: false