ghtorrent 0.4 → 0.5
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.
- data/CHANGELOG +24 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +40 -0
- data/README.md +23 -22
- data/bin/ght-data-retrieval +66 -24
- data/bin/ght-load +41 -19
- data/bin/ght-mirror-events +13 -16
- data/bin/ght-rm-dupl +119 -77
- data/lib/ghtorrent.rb +14 -4
- data/lib/ghtorrent/adapters/base_adapter.rb +17 -5
- data/lib/ghtorrent/adapters/mongo_persister.rb +122 -56
- data/lib/ghtorrent/api_client.rb +151 -16
- data/lib/ghtorrent/bson_orderedhash.rb +23 -0
- data/lib/ghtorrent/cache.rb +97 -0
- data/lib/ghtorrent/command.rb +43 -25
- data/lib/ghtorrent/gh_torrent_exception.rb +6 -0
- data/lib/ghtorrent/ghtorrent.rb +615 -164
- data/lib/ghtorrent/hash.rb +11 -0
- data/lib/ghtorrent/logging.rb +11 -7
- data/lib/ghtorrent/migrations/001_init_schema.rb +3 -3
- data/lib/ghtorrent/migrations/002_add_external_ref_ids.rb +2 -0
- data/lib/ghtorrent/migrations/003_add_orgs.rb +4 -1
- data/lib/ghtorrent/migrations/004_add_commit_comments.rb +4 -2
- data/lib/ghtorrent/migrations/005_add_repo_collaborators.rb +2 -0
- data/lib/ghtorrent/migrations/006_add_watchers.rb +2 -0
- data/lib/ghtorrent/migrations/007_add_pull_requests.rb +64 -0
- data/lib/ghtorrent/migrations/008_add_project_unq.rb +23 -0
- data/lib/ghtorrent/migrations/009_add_project_commit.rb +27 -0
- data/lib/ghtorrent/migrations/010_add_forks.rb +28 -0
- data/lib/ghtorrent/migrations/mysql_defaults.rb +6 -0
- data/lib/ghtorrent/persister.rb +3 -0
- data/lib/ghtorrent/retriever.rb +298 -102
- data/lib/ghtorrent/settings.rb +20 -1
- data/lib/ghtorrent/time.rb +5 -0
- data/lib/ghtorrent/utils.rb +22 -4
- data/lib/version.rb +5 -0
- metadata +173 -145
- data/lib/ghtorrent/call_stack.rb +0 -91
data/lib/ghtorrent/logging.rb
CHANGED
@@ -21,21 +21,25 @@ module GHTorrent
|
|
21
21
|
|
22
22
|
# Log a message at the given level.
|
23
23
|
def log(level, msg)
|
24
|
-
|
24
|
+
|
25
25
|
case level
|
26
26
|
when :fatal then
|
27
|
-
|
27
|
+
logger.fatal msg
|
28
28
|
when :error then
|
29
|
-
|
29
|
+
logger.error msg
|
30
30
|
when :warn then
|
31
|
-
|
31
|
+
logger.warn msg
|
32
32
|
when :info then
|
33
|
-
|
33
|
+
logger.info msg
|
34
34
|
when :debug then
|
35
|
-
|
35
|
+
logger.debug msg
|
36
36
|
else
|
37
|
-
|
37
|
+
logger.debug msg
|
38
38
|
end
|
39
39
|
end
|
40
|
+
|
41
|
+
def logger
|
42
|
+
raise Exception.new("Unimplemented")
|
43
|
+
end
|
40
44
|
end
|
41
45
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'sequel'
|
2
2
|
|
3
|
+
require 'ghtorrent/migrations/mysql_defaults'
|
4
|
+
|
3
5
|
Sequel.migration do
|
4
6
|
up do
|
5
7
|
puts("Creating table users")
|
@@ -9,9 +11,7 @@ Sequel.migration do
|
|
9
11
|
String :name
|
10
12
|
String :company, :null => true
|
11
13
|
String :location, :null => true
|
12
|
-
String :email, :null => true
|
13
|
-
TrueClass :hireable, :null => true
|
14
|
-
String :bio, :null => true
|
14
|
+
String :email, :null => true
|
15
15
|
DateTime :created_at, :null => false, :default=>Sequel::CURRENT_TIMESTAMP
|
16
16
|
end
|
17
17
|
|
@@ -1,12 +1,15 @@
|
|
1
1
|
require 'sequel'
|
2
2
|
|
3
|
+
require 'ghtorrent/migrations/mysql_defaults'
|
4
|
+
|
3
5
|
Sequel.migration do
|
4
6
|
up do
|
5
7
|
|
6
8
|
puts("Adding organization descriminator field to table users")
|
7
9
|
|
8
10
|
alter_table :users do
|
9
|
-
add_column :type,
|
11
|
+
add_column :type, String, :null => false, :default => 'USR'
|
12
|
+
add_constraint(:type_allowed_values, :type => %w[USR ORG])
|
10
13
|
end
|
11
14
|
|
12
15
|
puts("Updating users with default values")
|
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'sequel'
|
2
2
|
|
3
|
+
require 'ghtorrent/migrations/mysql_defaults'
|
4
|
+
|
3
5
|
Sequel.migration do
|
4
6
|
up do
|
5
7
|
|
@@ -9,7 +11,7 @@ Sequel.migration do
|
|
9
11
|
primary_key :id
|
10
12
|
foreign_key :commit_id, :commits, :null => false
|
11
13
|
foreign_key :user_id, :users, :null => false
|
12
|
-
String :body
|
14
|
+
String :body, :size => 256
|
13
15
|
Integer :line, :null => true
|
14
16
|
Integer :position, :null => true
|
15
17
|
Integer :comment_id, :null => false, :unique => true
|
@@ -24,4 +26,4 @@ Sequel.migration do
|
|
24
26
|
drop_table :commit_comments
|
25
27
|
|
26
28
|
end
|
27
|
-
end
|
29
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
|
3
|
+
require 'ghtorrent/migrations/mysql_defaults'
|
4
|
+
|
5
|
+
Sequel.migration do
|
6
|
+
up do
|
7
|
+
|
8
|
+
puts("Adding table pull requests")
|
9
|
+
|
10
|
+
create_table :pull_requests do
|
11
|
+
primary_key :id
|
12
|
+
foreign_key :head_repo_id, :projects
|
13
|
+
foreign_key :base_repo_id, :projects, :null => false
|
14
|
+
foreign_key :head_commit_id, :commits
|
15
|
+
foreign_key :base_commit_id, :commits, :null => false
|
16
|
+
foreign_key :user_id, :users, :null => false
|
17
|
+
Integer :pullreq_id, :null => false
|
18
|
+
TrueClass :intra_branch, :null => false
|
19
|
+
unique([:pullreq_id, :base_repo_id])
|
20
|
+
end
|
21
|
+
|
22
|
+
puts("Adding table pull request history")
|
23
|
+
|
24
|
+
create_table :pull_request_history do
|
25
|
+
primary_key :id
|
26
|
+
foreign_key :pull_request_id, :pull_requests, :null => false
|
27
|
+
DateTime :created_at, :null => false, :default=>Sequel::CURRENT_TIMESTAMP
|
28
|
+
String :ext_ref_id, :null => false, :size => 24, :default => "0"
|
29
|
+
String :action, :null => false
|
30
|
+
check(:action=>%w[opened closed merged synchronize reopened])
|
31
|
+
end
|
32
|
+
|
33
|
+
puts("Adding table pull request commits")
|
34
|
+
|
35
|
+
create_table :pull_request_commits do
|
36
|
+
foreign_key :pull_request_id, :pull_requests, :null => false
|
37
|
+
foreign_key :commit_id, :commits, :null => false
|
38
|
+
primary_key [:pull_request_id, :commit_id]
|
39
|
+
end
|
40
|
+
|
41
|
+
puts("Adding table pull request comments")
|
42
|
+
|
43
|
+
create_table :pull_request_comments do
|
44
|
+
foreign_key :pull_request_id, :pull_requests, :null => false
|
45
|
+
foreign_key :user_id, :users, :null => false
|
46
|
+
Long :comment_id, :null => false
|
47
|
+
Integer :position, :null => true
|
48
|
+
String :body, :size => 256
|
49
|
+
foreign_key :commit_id, :commits, :null => false
|
50
|
+
DateTime :created_at, :null => false, :default=>Sequel::CURRENT_TIMESTAMP
|
51
|
+
String :ext_ref_id, :null => false, :size => 24, :default => "0"
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
down do
|
57
|
+
|
58
|
+
drop_table :pull_requests
|
59
|
+
drop_table :pull_request_history
|
60
|
+
drop_table :pull_request_commits
|
61
|
+
drop_table :pull_request_comments
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
|
3
|
+
require 'ghtorrent/migrations/mysql_defaults'
|
4
|
+
|
5
|
+
Sequel.migration do
|
6
|
+
up do
|
7
|
+
|
8
|
+
puts("Adding unique(name, owner) constraint to table projects")
|
9
|
+
|
10
|
+
alter_table :projects do
|
11
|
+
add_unique_constraint([:name, :owner_id])
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
down do
|
16
|
+
|
17
|
+
puts("Removing unique(name, owner) constraint from table projects")
|
18
|
+
|
19
|
+
alter_table :projects do
|
20
|
+
drop_unique_constraint([:name, :owner_id])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
|
3
|
+
require 'ghtorrent/migrations/mysql_defaults'
|
4
|
+
|
5
|
+
Sequel.migration do
|
6
|
+
up do
|
7
|
+
|
8
|
+
puts("Create table project_commits")
|
9
|
+
create_table :project_commits do
|
10
|
+
foreign_key :project_id, :projects
|
11
|
+
foreign_key :commit_id, :commits
|
12
|
+
primary_key [:project_id, :commit_id]
|
13
|
+
end
|
14
|
+
|
15
|
+
puts("Migrating data from commits to project_commits")
|
16
|
+
transaction(:rollback => :reraise, :isolation => :committed) do
|
17
|
+
self[:project_commits].insert([:project_id, :commit_id],
|
18
|
+
self[:commits].select(:project_id, :id))
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
down do
|
24
|
+
|
25
|
+
drop_table :project_commits
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
|
3
|
+
require 'ghtorrent/migrations/mysql_defaults'
|
4
|
+
|
5
|
+
Sequel.migration do
|
6
|
+
up do
|
7
|
+
|
8
|
+
puts("Adding table forks")
|
9
|
+
|
10
|
+
create_table :forks do
|
11
|
+
foreign_key :forked_project_id, :projects, :null => false
|
12
|
+
foreign_key :forked_from_id, :projects, :null => false
|
13
|
+
Integer :fork_id, :null => false, :unique => true
|
14
|
+
DateTime :created_at, :null => false,
|
15
|
+
:default => Sequel::CURRENT_TIMESTAMP
|
16
|
+
String :ext_ref_id, :null => false, :size => 24, :default => "0"
|
17
|
+
primary_key([:forked_project_id, :forked_from_id])
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
down do
|
23
|
+
|
24
|
+
puts("Droping table forks")
|
25
|
+
drop_table :forks
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
data/lib/ghtorrent/persister.rb
CHANGED
data/lib/ghtorrent/retriever.rb
CHANGED
@@ -1,29 +1,37 @@
|
|
1
1
|
require 'uri'
|
2
2
|
|
3
|
+
require 'ghtorrent/api_client'
|
4
|
+
require 'ghtorrent/settings'
|
5
|
+
require 'ghtorrent/utils'
|
6
|
+
require 'ghtorrent/gh_torrent_exception'
|
7
|
+
|
3
8
|
module GHTorrent
|
4
9
|
module Retriever
|
5
10
|
|
11
|
+
include GHTorrent::Settings
|
6
12
|
include GHTorrent::Utils
|
7
13
|
include GHTorrent::APIClient
|
8
14
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
|
15
|
+
def ext_uniq
|
16
|
+
raise Exception("Unimplemented")
|
17
|
+
end
|
18
|
+
|
19
|
+
def persister
|
20
|
+
raise Exception("Unimplemented")
|
13
21
|
end
|
14
22
|
|
15
23
|
def retrieve_user_byusername(user)
|
16
|
-
stored_user =
|
24
|
+
stored_user = persister.find(:users, {'login' => user})
|
17
25
|
if stored_user.empty?
|
18
26
|
url = ghurl "users/#{user}"
|
19
27
|
u = api_request(url)
|
20
28
|
|
21
29
|
if u.empty?
|
22
|
-
|
30
|
+
return
|
23
31
|
end
|
24
32
|
|
25
|
-
unq =
|
26
|
-
u[
|
33
|
+
unq = persister.store(:users, u)
|
34
|
+
u[ext_uniq] = unq
|
27
35
|
what = user_type(u['type'])
|
28
36
|
info "Retriever: New #{what} #{user}"
|
29
37
|
u
|
@@ -41,62 +49,79 @@ module GHTorrent
|
|
41
49
|
url = ghurl("legacy/user/email/#{URI.escape(email)}")
|
42
50
|
r = api_request(url)
|
43
51
|
|
44
|
-
|
45
|
-
|
52
|
+
unless r.empty? or r['user']['login'].nil?
|
53
|
+
info "Retriever: User #{r['user']['login']} retrieved by email #{email}"
|
54
|
+
retrieve_user_byusername(r['user']['login'])
|
55
|
+
else
|
56
|
+
if r.empty?
|
57
|
+
nil
|
58
|
+
else
|
59
|
+
u = r['user']
|
60
|
+
unq = persister.store(:users, u)
|
61
|
+
u[ext_uniq] = unq
|
62
|
+
what = user_type(u['type'])
|
63
|
+
info "Retriever: New #{what} #{user}"
|
64
|
+
u
|
65
|
+
end
|
66
|
+
end
|
46
67
|
end
|
47
68
|
|
48
|
-
def
|
49
|
-
|
69
|
+
def retrieve_user_follower(followed, follower)
|
70
|
+
stored_item = persister.find(:followers, {'follows' => followed,
|
71
|
+
'login' => follower})
|
72
|
+
|
73
|
+
if stored_item.empty?
|
74
|
+
retrieve_user_followers(followed).find{|x| x['login'] == follower}
|
75
|
+
else
|
76
|
+
stored_item.first
|
77
|
+
end
|
78
|
+
end
|
50
79
|
|
80
|
+
def retrieve_user_followers(user)
|
51
81
|
followers = paged_api_request(ghurl "users/#{user}/followers")
|
52
82
|
followers.each do |x|
|
53
83
|
x['follows'] = user
|
54
84
|
|
55
|
-
exists = !
|
56
|
-
|
57
|
-
}.nil?
|
85
|
+
exists = !persister.find(:followers, {'follows' => user,
|
86
|
+
'login' => x['login']}).empty?
|
58
87
|
|
59
88
|
if not exists
|
60
|
-
|
89
|
+
persister.store(:followers, x)
|
61
90
|
info "Retriever: Added follower #{user} -> #{x['login']}"
|
62
91
|
else
|
63
92
|
debug "Retriever: Follower #{user} -> #{x['login']} exists"
|
64
93
|
end
|
65
94
|
end
|
66
95
|
|
67
|
-
|
96
|
+
persister.find(:followers, {'follows' => user})
|
68
97
|
end
|
69
98
|
|
70
99
|
# Retrieve a single commit from a repo
|
71
100
|
def retrieve_commit(repo, sha, user)
|
72
|
-
commit =
|
101
|
+
commit = persister.find(:commits, {'sha' => "#{sha}"})
|
73
102
|
|
74
103
|
if commit.empty?
|
75
104
|
url = ghurl "repos/#{user}/#{repo}/commits/#{sha}"
|
76
105
|
c = api_request(url)
|
77
106
|
|
78
107
|
if c.empty?
|
79
|
-
|
108
|
+
return
|
80
109
|
end
|
81
110
|
|
82
|
-
unq =
|
83
|
-
info "Retriever: New commit #{repo} -> #{sha}"
|
84
|
-
c[
|
111
|
+
unq = persister.store(:commits, c)
|
112
|
+
info "Retriever: New commit #{user}/#{repo} -> #{sha}"
|
113
|
+
c[ext_uniq] = unq
|
85
114
|
c
|
86
115
|
else
|
87
|
-
debug "Retriever: Already got commit #{repo} -> #{sha}"
|
116
|
+
debug "Retriever: Already got commit #{user}/#{repo} -> #{sha}"
|
88
117
|
commit.first
|
89
118
|
end
|
90
119
|
end
|
91
120
|
|
92
|
-
# Retrieve
|
121
|
+
# Retrieve up to 30 * +:mirror_commit_pages_new_repo+ commits
|
93
122
|
# starting from the provided +sha+
|
94
123
|
def retrieve_commits(repo, sha, user)
|
95
|
-
last_sha = if sha.nil?
|
96
|
-
"master"
|
97
|
-
else
|
98
|
-
sha
|
99
|
-
end
|
124
|
+
last_sha = if sha.nil? then "master" else sha end
|
100
125
|
|
101
126
|
url = ghurl "repos/#{user}/#{repo}/commits?last_sha=#{last_sha}"
|
102
127
|
commits = paged_api_request(url, config(:mirror_commit_pages_new_repo))
|
@@ -108,19 +133,19 @@ module GHTorrent
|
|
108
133
|
|
109
134
|
|
110
135
|
def retrieve_repo(user, repo)
|
111
|
-
stored_repo =
|
136
|
+
stored_repo = persister.find(:repos, {'owner.login' => user,
|
112
137
|
'name' => repo })
|
113
138
|
if stored_repo.empty?
|
114
139
|
url = ghurl "repos/#{user}/#{repo}"
|
115
140
|
r = api_request(url)
|
116
141
|
|
117
142
|
if r.empty?
|
118
|
-
|
143
|
+
return
|
119
144
|
end
|
120
145
|
|
121
|
-
unq =
|
146
|
+
unq = persister.store(:repos, r)
|
122
147
|
info "Retriever: New repo #{user} -> #{repo}"
|
123
|
-
r[
|
148
|
+
r[ext_uniq] = unq
|
124
149
|
r
|
125
150
|
else
|
126
151
|
debug "Retriever: Already got repo #{user} -> #{repo}"
|
@@ -142,51 +167,49 @@ module GHTorrent
|
|
142
167
|
|
143
168
|
# Retrieve organization members
|
144
169
|
def retrieve_org_members(org)
|
145
|
-
|
146
|
-
stored_org_members = @persister.find(:org_members, {'org' => org})
|
170
|
+
stored_org_members = persister.find(:org_members, {'org' => org})
|
147
171
|
|
148
172
|
org_members = paged_api_request(ghurl "orgs/#{org}/members")
|
149
173
|
org_members.each do |x|
|
150
174
|
x['org'] = org
|
151
175
|
|
152
176
|
exists = !stored_org_members.find { |f|
|
153
|
-
f['org'] ==
|
177
|
+
f['org'] == org && f['login'] == x['login']
|
154
178
|
}.nil?
|
155
179
|
|
156
180
|
if not exists
|
157
|
-
|
158
|
-
info "Retriever: Added member #{org} -> #{x['login']}"
|
181
|
+
persister.store(:org_members, x)
|
182
|
+
info "Retriever: Added org member #{org} -> #{x['login']}"
|
159
183
|
else
|
160
|
-
debug "Retriever: Member #{org} -> #{x['login']} exists"
|
184
|
+
debug "Retriever: Org Member #{org} -> #{x['login']} exists"
|
161
185
|
end
|
162
186
|
end
|
163
187
|
|
164
|
-
|
188
|
+
persister.find(:org_members, {'org' => org}).map{|o| retrieve_org(o['login'])}
|
165
189
|
end
|
166
190
|
|
167
191
|
# Retrieve all comments for a single commit
|
168
192
|
def retrieve_commit_comments(user, repo, sha)
|
169
|
-
stored_comments = @persister.find(:commit_comments, {'commit_id' => sha})
|
170
193
|
retrieved_comments = paged_api_request(ghurl "repos/#{user}/#{repo}/commits/#{sha}/comments")
|
171
194
|
|
172
|
-
retrieved_comments.each{ |x|
|
195
|
+
retrieved_comments.each { |x|
|
173
196
|
x['repo'] = repo
|
174
197
|
x['user'] = user
|
175
198
|
x['commit_id'] = sha
|
176
199
|
|
177
|
-
if
|
200
|
+
if persister.find(:commit_comments, {'repo' => repo,
|
178
201
|
'user' => user,
|
179
202
|
'id' => x['id']}).empty?
|
180
|
-
|
203
|
+
persister.store(:commit_comments, x)
|
181
204
|
end
|
182
205
|
}
|
183
|
-
|
184
|
-
|
206
|
+
persister.find(:commit_comments, {'commit_id' => sha})
|
207
|
+
end
|
185
208
|
|
186
|
-
|
209
|
+
# Retrieve a single comment
|
187
210
|
def retrieve_commit_comment(user, repo, id)
|
188
211
|
|
189
|
-
comment =
|
212
|
+
comment = persister.find(:commit_comments, {'repo' => repo,
|
190
213
|
'user' => user,
|
191
214
|
'id' => id}).first
|
192
215
|
if comment.nil?
|
@@ -199,10 +222,10 @@ module GHTorrent
|
|
199
222
|
|
200
223
|
r['repo'] = repo
|
201
224
|
r['user'] = user
|
202
|
-
|
225
|
+
persister.store(:commit_comments, r)
|
203
226
|
info "Retriever: Added commit comment #{r['commit_id']} -> #{r['id']}"
|
204
|
-
|
205
|
-
|
227
|
+
persister.find(:commit_comments, {'repo' => repo, 'user' => user,
|
228
|
+
'id' => id}).first
|
206
229
|
else
|
207
230
|
debug "Retriever: Commit comment #{comment['commit_id']} -> #{comment['id']} exists"
|
208
231
|
comment
|
@@ -211,91 +234,264 @@ module GHTorrent
|
|
211
234
|
|
212
235
|
# Retrieve all collaborators for a repository
|
213
236
|
def retrieve_repo_collaborators(user, repo)
|
237
|
+
repo_bound_items(user, repo, :repo_collaborators,
|
238
|
+
"repos/#{user}/#{repo}/collaborators",
|
239
|
+
{'repo' => repo, 'owner' => user},
|
240
|
+
'login')
|
241
|
+
end
|
242
|
+
|
243
|
+
# Retrieve a single repository collaborator
|
244
|
+
def retrieve_repo_collaborator(user, repo, new_member)
|
245
|
+
repo_bound_item(user, repo, new_member, :repo_collaborators,
|
246
|
+
"repos/#{user}/#{repo}/collaborators",
|
247
|
+
{'repo' => repo, 'owner' => user},
|
248
|
+
'login')
|
249
|
+
end
|
250
|
+
|
251
|
+
# Retrieve all watchers for a repository
|
252
|
+
def retrieve_watchers(user, repo)
|
253
|
+
repo_bound_items(user, repo, :watchers,
|
254
|
+
"repos/#{user}/#{repo}/watchers",
|
255
|
+
{'repo' => repo, 'owner' => user},
|
256
|
+
'login')
|
257
|
+
end
|
258
|
+
|
259
|
+
# Retrieve a single watcher for a repositry
|
260
|
+
def retrieve_watcher(user, repo, watcher)
|
261
|
+
repo_bound_item(user, repo, watcher, :watchers,
|
262
|
+
"repos/#{user}/#{repo}/watchers",
|
263
|
+
{'repo' => repo, 'owner' => user},
|
264
|
+
'login')
|
265
|
+
end
|
214
266
|
|
215
|
-
|
216
|
-
|
217
|
-
|
267
|
+
def retrieve_pull_requests(user, repo)
|
268
|
+
open = "repos/#{user}/#{repo}/pulls"
|
269
|
+
closed = "repos/#{user}/#{repo}/pulls?state=closed"
|
270
|
+
repo_bound_items(user, repo, :pull_requests,
|
271
|
+
[open, closed],
|
272
|
+
{'repo' => repo, 'owner' => user},
|
273
|
+
'number')
|
274
|
+
end
|
275
|
+
|
276
|
+
def retrieve_pull_request(user, repo, pullreq_id)
|
277
|
+
open = "repos/#{user}/#{repo}/pulls"
|
278
|
+
closed = "repos/#{user}/#{repo}/pulls?state=closed"
|
279
|
+
repo_bound_item(user, repo, pullreq_id, :pull_requests,
|
280
|
+
[open, closed],
|
281
|
+
{'repo' => repo, 'owner' => user,
|
282
|
+
'number' => pullreq_id},
|
283
|
+
'number')
|
284
|
+
end
|
285
|
+
|
286
|
+
def retrieve_forks(user, repo)
|
287
|
+
repo_bound_items(user, repo, :forks,
|
288
|
+
"repos/#{user}/#{repo}/forks",
|
289
|
+
{'repo' => repo, 'owner' => user},
|
290
|
+
'id')
|
291
|
+
end
|
292
|
+
|
293
|
+
def retrieve_fork(user, repo, fork_id)
|
294
|
+
repo_bound_item(user, repo, fork_id, :forks,
|
295
|
+
"repos/#{user}/#{repo}/forks",
|
296
|
+
{'repo' => repo, 'owner' => user},
|
297
|
+
'id')
|
298
|
+
end
|
218
299
|
|
219
|
-
|
220
|
-
|
300
|
+
def retrieve_pull_req_commits(user, repo, pullreq_id)
|
301
|
+
is_intra_branch = Proc.new do |req|
|
302
|
+
req['head']['repo'].nil?
|
303
|
+
end
|
304
|
+
|
305
|
+
pull_req = retrieve_pull_request(user, repo, pullreq_id)
|
306
|
+
|
307
|
+
unless is_intra_branch.call(pull_req)
|
308
|
+
head_user = pull_req['head']['repo']['owner']['login']
|
309
|
+
head_repo = pull_req['head']['repo']['name']
|
310
|
+
|
311
|
+
commits = paged_api_request(ghurl "repos/#{user}/#{repo}/pulls/#{pullreq_id}/commits")
|
312
|
+
commits.map { |x|
|
313
|
+
retrieve_commit(head_repo, x['sha'], head_user)
|
314
|
+
}
|
315
|
+
else
|
316
|
+
commits = paged_api_request(ghurl "repos/#{user}/#{repo}/pulls/#{pullreq_id}/commits")
|
317
|
+
commits.map { |x|
|
318
|
+
retrieve_commit(repo, x['sha'], user)
|
319
|
+
}
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
def retrieve_pull_req_comments(owner, repo, pullreq_id)
|
324
|
+
review_comments_url = ghurl "repos/#{owner}/#{repo}/pulls/#{pullreq_id}/comments"
|
325
|
+
|
326
|
+
url = review_comments_url
|
327
|
+
retrieved_comments = paged_api_request url
|
328
|
+
|
329
|
+
retrieved_comments.each { |x|
|
330
|
+
x['owner'] = owner
|
221
331
|
x['repo'] = repo
|
222
|
-
x['
|
332
|
+
x['issue_id'] = pullreq_id
|
223
333
|
|
224
|
-
|
225
|
-
|
226
|
-
|
334
|
+
if persister.find(:pull_request_comments, {'owner' => owner,
|
335
|
+
'repo' => repo,
|
336
|
+
'pullreq_id' => pullreq_id,
|
337
|
+
'id' => x['id']}).empty?
|
338
|
+
persister.store(:pull_request_comments, x)
|
339
|
+
end
|
340
|
+
}
|
227
341
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
342
|
+
persister.find(:pull_request_comments, {'owner' => owner, 'repo' => repo,
|
343
|
+
'pullreq_id' => pullreq_id})
|
344
|
+
end
|
345
|
+
|
346
|
+
def retrieve_pull_req_comment(owner, repo, pullreq_id, comment_id)
|
347
|
+
comment = persister.find(:pull_request_comments, {'repo' => repo,
|
348
|
+
'owner' => owner,
|
349
|
+
'pullreq_id' => pullreq_id,
|
350
|
+
'id' => comment_id}).first
|
351
|
+
if comment.nil?
|
352
|
+
r = api_request(ghurl "repos/#{owner}/#{repo}/pulls/comments/#{comment_id}")
|
353
|
+
|
354
|
+
if r.empty?
|
355
|
+
debug "Retriever: Pullreq comment #{owner}/#{repo} #{pullreq_id}->#{comment_id} deleted"
|
356
|
+
return
|
233
357
|
end
|
358
|
+
|
359
|
+
r['repo'] = repo
|
360
|
+
r['owner'] = owner
|
361
|
+
r['pullreq_id'] = pullreq_id
|
362
|
+
persister.store(:pull_request_comments, r)
|
363
|
+
info "Retriever: Added pullreq comment #{owner}/#{repo} #{pullreq_id}->#{comment_id}"
|
364
|
+
persister.find(:pull_request_comments, {'repo' => repo, 'owner' => owner,
|
365
|
+
'pullreq_id' => pullreq_id,
|
366
|
+
'id' => comment_id}).first
|
367
|
+
else
|
368
|
+
debug "Retriever: Pullreq comment #{owner}/#{repo} #{pullreq_id}->#{comment_id} exists"
|
369
|
+
comment
|
234
370
|
end
|
371
|
+
end
|
235
372
|
|
236
|
-
|
373
|
+
def retrieve_issues(user, repo)
|
374
|
+
repo_bound_items(user, repo, :issues,
|
375
|
+
"repos/#{user}/#{repo}/issues",
|
376
|
+
{'repo' => repo, 'owner' => user},
|
377
|
+
'id')
|
237
378
|
end
|
238
379
|
|
239
|
-
|
240
|
-
|
380
|
+
def retrieve_issue(user, repo, issue_id)
|
381
|
+
repo_bound_item(user, repo, issue_id, :issues,
|
382
|
+
"repos/#{user}/#{repo}/issues/#{issue_id}",
|
383
|
+
{'repo' => repo, 'owner' => user},
|
384
|
+
'id')
|
385
|
+
end
|
386
|
+
|
387
|
+
def retrieve_issue_comments(owner, repo, issue_id)
|
388
|
+
url = ghurl "repos/#{owner}/#{repo}/issues/#{issue_id}/comments"
|
389
|
+
retrieved_comments = paged_api_request url
|
241
390
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
391
|
+
retrieved_comments.each { |x|
|
392
|
+
x['owner'] = owner
|
393
|
+
x['repo'] = repo
|
394
|
+
x['issue_id'] = issue_id
|
395
|
+
|
396
|
+
if persister.find(:issue_comments, {'owner' => owner,
|
397
|
+
'repo' => repo,
|
398
|
+
'issue_id' => issue_id,
|
399
|
+
'id' => x['id']}).empty?
|
400
|
+
persister.store(:issue_comments, x)
|
401
|
+
end
|
402
|
+
}
|
403
|
+
persister.find(:issue_comments, {'owner' => owner, 'repo' => repo,
|
404
|
+
'issue_id' => issue_id})
|
405
|
+
end
|
406
|
+
|
407
|
+
def retrieve_issue_comment(owner, repo, issue_id, comment_id)
|
408
|
+
comment = persister.find(:issue_comments, {'repo' => repo,
|
409
|
+
'owner' => owner,
|
410
|
+
'issue_id' => issue_id,
|
411
|
+
'id' => comment_id}).first
|
412
|
+
if comment.nil?
|
413
|
+
r = api_request(ghurl "repos/#{owner}/#{repo}/issues/#{issue_id}/comments/#{comment_id}")
|
414
|
+
|
415
|
+
if r.empty?
|
416
|
+
debug "Retriever: Issue comment #{owner}/#{repo} #{issue_id}->#{comment_id} deleted"
|
417
|
+
return
|
418
|
+
end
|
246
419
|
|
247
|
-
|
248
|
-
|
420
|
+
r['repo'] = repo
|
421
|
+
r['owner'] = owner
|
422
|
+
x['issue_id'] = issue_id
|
423
|
+
persister.store(:issue_comments, r)
|
424
|
+
info "Retriever: Added issue comment #{owner}/#{repo} #{issue_id}->#{comment_id}"
|
425
|
+
persister.find(:issue_comments, {'repo' => repo, 'owner' => owner,
|
426
|
+
'issue_id' => issue_id,
|
427
|
+
'id' => comment_id}).first
|
428
|
+
r
|
249
429
|
else
|
250
|
-
|
430
|
+
debug "Retriever: Commit comment #{owner}/#{repo} #{issue_id}->#{comment_id} exists"
|
431
|
+
comment
|
251
432
|
end
|
252
433
|
end
|
253
434
|
|
254
|
-
#
|
255
|
-
def
|
256
|
-
|
257
|
-
|
435
|
+
# Get current Github events
|
436
|
+
def get_events
|
437
|
+
api_request "https://api.github.com/events"
|
438
|
+
end
|
439
|
+
|
440
|
+
private
|
441
|
+
|
442
|
+
def repo_bound_items(user, repo, entity, urls, selector, descriminator,
|
443
|
+
item_id = nil)
|
258
444
|
|
259
|
-
|
260
|
-
|
445
|
+
items = if urls.class == Array
|
446
|
+
urls.map { |url| paged_api_request(ghurl url) }.flatten
|
447
|
+
else
|
448
|
+
paged_api_request(ghurl urls)
|
449
|
+
end
|
450
|
+
|
451
|
+
items.each do |x|
|
261
452
|
x['repo'] = repo
|
262
453
|
x['owner'] = user
|
263
454
|
|
264
|
-
exists = !
|
265
|
-
|
266
|
-
}.nil?
|
455
|
+
exists = !repo_bound_instance(entity, selector,
|
456
|
+
descriminator, x[descriminator]).empty?
|
267
457
|
|
268
458
|
if not exists
|
269
|
-
|
270
|
-
info "Retriever: Added
|
459
|
+
persister.store(entity, x)
|
460
|
+
info "Retriever: Added #{entity} #{user}/#{repo} -> #{x[descriminator]}"
|
271
461
|
else
|
272
|
-
debug "Retriever:
|
462
|
+
debug "Retriever: #{entity} #{user}/#{repo} -> #{x[descriminator]} exists"
|
273
463
|
end
|
274
464
|
end
|
275
465
|
|
276
|
-
|
466
|
+
if item_id.nil?
|
467
|
+
persister.find(entity, selector)
|
468
|
+
else
|
469
|
+
repo_bound_instance(entity, selector, descriminator, item_id)
|
470
|
+
end
|
277
471
|
end
|
278
472
|
|
279
|
-
|
280
|
-
|
281
|
-
stored_watcher = @persister.find(:watchers,
|
282
|
-
{'repo' => repo,
|
283
|
-
'owner' => user,
|
284
|
-
'login' => watcher})
|
473
|
+
def repo_bound_item(user, repo, item_id, entity, url, selector, descriminator)
|
474
|
+
stored_item = repo_bound_instance(entity, selector, descriminator, item_id)
|
285
475
|
|
286
|
-
if
|
287
|
-
|
476
|
+
if stored_item.empty?
|
477
|
+
repo_bound_items(user, repo, entity, url, selector, descriminator,
|
478
|
+
item_id).first
|
288
479
|
else
|
289
|
-
|
480
|
+
stored_item.first
|
290
481
|
end
|
291
482
|
end
|
292
483
|
|
293
|
-
|
294
|
-
def get_events
|
295
|
-
api_request "https://api.github.com/events"
|
296
|
-
end
|
484
|
+
def repo_bound_instance(entity, selector, descriminator, item_id)
|
297
485
|
|
298
|
-
|
486
|
+
id = if item_id.to_i.to_s != item_id
|
487
|
+
item_id # item_id is string
|
488
|
+
else
|
489
|
+
item_id.to_i # convert to int
|
490
|
+
end
|
491
|
+
|
492
|
+
instance_selector = selector.merge({descriminator => id})
|
493
|
+
persister.find(entity, instance_selector)
|
494
|
+
end
|
299
495
|
|
300
496
|
def ghurl(path)
|
301
497
|
config(:mirror_urlbase) + path
|