github-api-client 0.3.3 → 0.4.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/Gemfile +1 -15
- data/Gemfile.lock +23 -25
- data/NEWS +18 -0
- data/Rakefile +38 -0
- data/TODO +6 -0
- data/bin/api-browser.rb +12 -17
- data/bin/github-api-client +33 -0
- data/db/migrate/001_migrate_everything.rb +18 -0
- data/features/user_api.feature +88 -0
- data/github-api-client.gemspec +41 -0
- data/lib/github-api-client.rb +31 -9
- data/lib/github-api-client/browser.rb +11 -8
- data/lib/github-api-client/config.rb +0 -5
- data/lib/github-api-client/fetchers.rb +11 -0
- data/lib/github-api-client/fetchers/repo.rb +32 -0
- data/lib/github-api-client/fetchers/user.rb +49 -0
- data/lib/github-api-client/helpers.rb +15 -0
- data/lib/github-api-client/resource.rb +72 -0
- data/lib/github-api-client/resources/repo.rb +13 -0
- data/lib/github-api-client/resources/user.rb +10 -0
- data/lib/github-api-client/strategies/ask.rb +14 -0
- data/lib/github-api-client/strategies/local.rb +14 -0
- data/lib/github-api-client/strategies/remote.rb +14 -0
- data/lib/github-api-client/strategy.rb +15 -0
- data/lib/github-api-client/version.rb +10 -0
- data/new_design +4 -0
- metadata +62 -68
- data/VERSION +0 -1
- data/db/migrate/001_create_users.rb +0 -21
- data/db/migrate/002_create_user_followings.rb +0 -12
- data/db/migrate/003_create_repos.rb +0 -32
- data/db/migrate/004_create_repo_watchings.rb +0 -12
- data/db/migrate/005_create_organizations.rb +0 -15
- data/db/migrate/006_create_organizations_members.rb +0 -12
- data/lib/github-api-client/organization.rb +0 -64
- data/lib/github-api-client/repo.rb +0 -99
- data/lib/github-api-client/user.rb +0 -186
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.3.3
|
@@ -1,21 +0,0 @@
|
|
1
|
-
class CreateUsers < ActiveRecord::Migration
|
2
|
-
def self.up
|
3
|
-
create_table :users do |t|
|
4
|
-
%w(login token type name company location blog email language permission).each do |attr|
|
5
|
-
t.string attr
|
6
|
-
end
|
7
|
-
|
8
|
-
%w(gravatar_id score record).each do |attr|
|
9
|
-
t.integer attr
|
10
|
-
end
|
11
|
-
|
12
|
-
%w(created_at pushed).each do |attr|
|
13
|
-
t.datetime attr
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.down
|
19
|
-
drop_table :users
|
20
|
-
end
|
21
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
class CreateRepos < ActiveRecord::Migration
|
2
|
-
def self.up
|
3
|
-
create_table :repos do |t|
|
4
|
-
%w(name description url language integrate_branch homepage source).each do |attr|
|
5
|
-
t.string attr
|
6
|
-
end
|
7
|
-
|
8
|
-
%w(parent).each do |attr|
|
9
|
-
t.references attr
|
10
|
-
end
|
11
|
-
|
12
|
-
t.references :owner, :polymorphic => true
|
13
|
-
|
14
|
-
# TODO: organization temporarily a string, only when there's no organization model
|
15
|
-
%w(size score).each do |attr|
|
16
|
-
t.integer attr
|
17
|
-
end
|
18
|
-
|
19
|
-
%w(has_downloads b_fork deleted locked has_wiki private open_issues has_issues).each do |attr|
|
20
|
-
t.boolean attr
|
21
|
-
end
|
22
|
-
|
23
|
-
%w(created_at pushed_at).each do |attr|
|
24
|
-
t.datetime attr
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.down
|
30
|
-
drop_table :repos
|
31
|
-
end
|
32
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
class CreateOrganizations < ActiveRecord::Migration
|
2
|
-
def self.up
|
3
|
-
create_table :organizations do |t|
|
4
|
-
%w(name company location blog type login email gravatar_id billing_email permission).each do |attr|
|
5
|
-
t.string attr
|
6
|
-
end
|
7
|
-
|
8
|
-
t.timestamps
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.down
|
13
|
-
drop_table :organizations
|
14
|
-
end
|
15
|
-
end
|
@@ -1,12 +0,0 @@
|
|
1
|
-
class CreateOrganizationsMembers < ActiveRecord::Migration
|
2
|
-
def self.up
|
3
|
-
create_table :organizations_members, :id => false do |t|
|
4
|
-
t.references :user
|
5
|
-
t.references :organization
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
def self.down
|
10
|
-
drop_table :organizations_member
|
11
|
-
end
|
12
|
-
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
module GitHub
|
2
|
-
class Organization < ActiveRecord::Base
|
3
|
-
has_and_belongs_to_many :members, :class_name => 'GitHub::User', :join_table => 'organizations_members'
|
4
|
-
has_many :repositories, :class_name => 'GitHub::Repo', :as => :owner
|
5
|
-
|
6
|
-
def get
|
7
|
-
self.update_attributes(
|
8
|
-
GitHub::Base.parse_attributes(:org_get,
|
9
|
-
YAML::load(
|
10
|
-
GitHub::Browser.get("/organizations/#{self.login}"))['organization']))
|
11
|
-
self
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.get(login)
|
15
|
-
o = GitHub::Organization.find_by_login(login)
|
16
|
-
o ||= GitHub::Organization.new(:login => login).get
|
17
|
-
end
|
18
|
-
|
19
|
-
def fetch(*things)
|
20
|
-
things.each do |thing|
|
21
|
-
case thing
|
22
|
-
when :self then get
|
23
|
-
when :members then get_members
|
24
|
-
when :repositories then get_repositories
|
25
|
-
end
|
26
|
-
end
|
27
|
-
self
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
def get_members
|
32
|
-
members = YAML::load(GitHub::Browser.get "/organizations/#{login}/public_members")['users']
|
33
|
-
puts "Fetching members for #{"organization".color(:magenta).bright} #{self.login.dup.color(:green).bright}"
|
34
|
-
i, count = 0, members.count.to_s.color(:green).bright
|
35
|
-
self.transaction do
|
36
|
-
members.each do |user|
|
37
|
-
i += 1
|
38
|
-
u = GitHub::User.find_or_create_by_login(user['login'])
|
39
|
-
self.association(:members).find_or_create u
|
40
|
-
print "\r#{i.to_s.color(:yellow).bright}/#{count}"
|
41
|
-
end
|
42
|
-
end
|
43
|
-
puts nil
|
44
|
-
self
|
45
|
-
end
|
46
|
-
|
47
|
-
def get_repositories
|
48
|
-
repos = YAML::load(GitHub::Browser.get "/organizations/#{login}/public_repositories")['repositories']
|
49
|
-
puts "Fetching repositories for #{"organization".color(:magenta).bright} #{self.login.dup.color(:green).bright}"
|
50
|
-
i, count = 0, repos.count.to_s.color(:green).bright
|
51
|
-
self.transaction do
|
52
|
-
repos.each do |repo|
|
53
|
-
i += 1
|
54
|
-
r = GitHub::Repo.find_by_url(repo[:url])
|
55
|
-
r ||= GitHub::Repo.create(GitHub::Base.parse_attributes :org_repo_index, repo)
|
56
|
-
print "\r#{i.to_s.color(:yellow).bright}/#{count}"
|
57
|
-
end
|
58
|
-
end
|
59
|
-
puts nil
|
60
|
-
self
|
61
|
-
end
|
62
|
-
|
63
|
-
end
|
64
|
-
end
|
@@ -1,99 +0,0 @@
|
|
1
|
-
module GitHub
|
2
|
-
class Repo < ActiveRecord::Base
|
3
|
-
belongs_to :owner, :polymorphic => true
|
4
|
-
belongs_to :parent, :class_name => 'GitHub::Repo'
|
5
|
-
has_and_belongs_to_many :watchers, :class_name => 'GitHub::User', :join_table => 'repo_watchings', :foreign_key => 'repo_id', :association_foreign_key => 'watcher_id'
|
6
|
-
|
7
|
-
def get
|
8
|
-
parser = case self.owner_type
|
9
|
-
when 'GitHub::User'
|
10
|
-
:repo_get
|
11
|
-
when 'GitHub::Organization'
|
12
|
-
:org_repo_get
|
13
|
-
end
|
14
|
-
self.update_attributes GitHub::Base.parse_attributes(parser,
|
15
|
-
YAML::load(
|
16
|
-
GitHub::Browser.get("/repos/show/#{self.permalink}"))['repository'])
|
17
|
-
self
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.get(information, o_type = :user)
|
21
|
-
#FIXME: permalink column must be present, comparing url's is surely not the most efficient way for the db
|
22
|
-
conditions = {:name => information.split('/').last}
|
23
|
-
if o_type == :user
|
24
|
-
conditions.merge! :owner_id => GitHub::User.find_or_create_by_login(information.split('/').first).id, :owner_type => 'GitHub::User'
|
25
|
-
else
|
26
|
-
conditions.merge! :owner_id => GitHub::Organization.find_or_create_by_login(information.split('/').first).id, :owner_type => 'GitHub::Organization'
|
27
|
-
end
|
28
|
-
if r = GitHub::Repo.where(conditions).first
|
29
|
-
r.get
|
30
|
-
else
|
31
|
-
r = GitHub::Repo.new(conditions).get
|
32
|
-
p r.parent
|
33
|
-
r
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def fetch(*things)
|
38
|
-
things.each do |thing|
|
39
|
-
case thing
|
40
|
-
when :self then get
|
41
|
-
when :watchers then get_watchers
|
42
|
-
end
|
43
|
-
end
|
44
|
-
self
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
def get_watchers
|
49
|
-
watchers = YAML::load(GitHub::Browser.get("/repos/show/#{self.permalink}/watchers"))['watchers']
|
50
|
-
puts "Fetching watchers for #{"repo".color(:blue).bright} #{self.permalink.dup.color(:green).bright}"
|
51
|
-
i, count = 0, watchers.count.to_s.color(:green).bright
|
52
|
-
self.transaction do
|
53
|
-
watchers.each do |watcher|
|
54
|
-
i += 1
|
55
|
-
attr = {:login => watcher}
|
56
|
-
self.association(:watchers).find_or_create(GitHub::User.find_or_create_by_login(attr))
|
57
|
-
print "\r#{i.to_s.color(:blue).bright}/#{count}"
|
58
|
-
end
|
59
|
-
end
|
60
|
-
puts nil
|
61
|
-
self
|
62
|
-
end
|
63
|
-
|
64
|
-
public
|
65
|
-
def owner_login=(user)
|
66
|
-
if user
|
67
|
-
self.owner = GitHub::User.find_or_create_by_login(user)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def organization_login=(organization)
|
72
|
-
if organization
|
73
|
-
self.owner = Organization.find_or_create_by_login(organization)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def parent=(permalink)
|
78
|
-
#FIXME: parent repo does not allow organization to be owner ATM
|
79
|
-
owner = GitHub::User.find_or_create_by_login permalink.split('/').first
|
80
|
-
name = permalink.split('/').last
|
81
|
-
repo = GitHub::Repo.where(:owner_id => owner.id, :owner_type => 'GitHub::Repo', :name => name).first
|
82
|
-
repo ||= GitHub::Repo.create(:owner => owner, :name => name)
|
83
|
-
self.parent_id = repo.id
|
84
|
-
end
|
85
|
-
|
86
|
-
def permalink
|
87
|
-
"#{owner.login}/#{name}"
|
88
|
-
end
|
89
|
-
|
90
|
-
# For future, when sql will be find_or_create_by_permalink
|
91
|
-
def permalink=(anything)
|
92
|
-
@permalink = permalink
|
93
|
-
end
|
94
|
-
|
95
|
-
def fork?
|
96
|
-
b_fork
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
@@ -1,186 +0,0 @@
|
|
1
|
-
module GitHub
|
2
|
-
# Basic model, stores retrieved user and his associations
|
3
|
-
class User < ActiveRecord::Base
|
4
|
-
has_and_belongs_to_many :followers, :foreign_key => 'follower_id', :association_foreign_key => 'following_id', :join_table => 'user_followings', :class_name => 'User'
|
5
|
-
has_and_belongs_to_many :followings, :foreign_key => 'following_id', :association_foreign_key => 'follower_id', :join_table => 'user_followings', :class_name => 'User'
|
6
|
-
has_many :repos, :class_name => 'GitHub::Repo', :as => :owner
|
7
|
-
|
8
|
-
# FIXME: Does GitHub allow a user to have multiple organizations?
|
9
|
-
has_and_belongs_to_many :organizations, :join_table => 'organizations_members'
|
10
|
-
|
11
|
-
# Fetches info about current_user from GitHub
|
12
|
-
# GitHub::User.new.build(:login => 'asd', :token => 'token').get #=> GitHub::User
|
13
|
-
# @return [GitHub::User] Chainable self object after syncing attributes with GitHub
|
14
|
-
def get
|
15
|
-
self.update_attributes(
|
16
|
-
GitHub::Base.parse_attributes(:user_get,
|
17
|
-
YAML::load(
|
18
|
-
GitHub::Browser.get("/user/show/#{self.login}"))['user']))
|
19
|
-
self
|
20
|
-
end
|
21
|
-
|
22
|
-
# Static function, that gets information about GitHub::User by login.
|
23
|
-
# === Examples
|
24
|
-
# GitHub::User.get('defunkt') #=> GitHub::User
|
25
|
-
# @param [String] login GitHub user login to fetch
|
26
|
-
# @return [GitHub::User] Newly created, in local database user synced with github
|
27
|
-
def self.get(login)
|
28
|
-
if u = GitHub::User.find_by_login(login)
|
29
|
-
u.get
|
30
|
-
else
|
31
|
-
u = GitHub::User.new(:login => login).fetch(:self)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
# Searches for users in GitHub database
|
36
|
-
# @param [String] login GitHub user login to search
|
37
|
-
# @return [Array<GitHub::User>] All users that matched login
|
38
|
-
def self.search(login)
|
39
|
-
users = []
|
40
|
-
YAML::load(GitHub::Browser.get("/user/search/#{login}"))['users'].each do |user|
|
41
|
-
users << GitHub::User.find_or_create_by_login(GitHub::Base.parse_attributes(:user_search, user))
|
42
|
-
end
|
43
|
-
users
|
44
|
-
end
|
45
|
-
|
46
|
-
# Experimental function, requests POST transmission to custom path of GitHub API
|
47
|
-
# @param [Array] route Route splitted like: ['users', 'search', 'chacon']
|
48
|
-
# @param [Hash] options Options to pass with the request
|
49
|
-
# @option [Hash] options 'values[email]' => 'test@api.com'
|
50
|
-
def set(route = [], options = {})
|
51
|
-
return GitHub::Browser.post "/#{route.join('/')}", options.merge(self.auth_info)
|
52
|
-
end
|
53
|
-
|
54
|
-
# End-user way to fetch information
|
55
|
-
# @param [Array<Symbol>] things Things to fetch for GitHub::User
|
56
|
-
# @option things [Symbol] :self Sync with GitHub Database
|
57
|
-
# @option things [Symbol] :followers Map followers from GitHub Database
|
58
|
-
# @option things [Symbol] :followings Map user's followings from GitHub
|
59
|
-
# @return [GitHub::User] Chainable, updated User
|
60
|
-
# @see GitHub::User#get
|
61
|
-
# @see GitHub::User#get_followers
|
62
|
-
def fetch(*things)
|
63
|
-
things.each do |thing|
|
64
|
-
case thing
|
65
|
-
when :self then get
|
66
|
-
when :followers then get_followers
|
67
|
-
when :followings then get_followings
|
68
|
-
when :organizations then get_organizations
|
69
|
-
when :repos then get_repos
|
70
|
-
end
|
71
|
-
end
|
72
|
-
self
|
73
|
-
end
|
74
|
-
|
75
|
-
# Executes when you got a real object
|
76
|
-
# @see GitHub::User#fetch
|
77
|
-
# @return GitHub::User Chainable after mapping followers association
|
78
|
-
private
|
79
|
-
def get_followers
|
80
|
-
users = YAML::load(GitHub::Browser.get "/user/show/#{login}/followers")['users'] || []
|
81
|
-
puts "Fetching followers for #{"user".color(:yellow).bright} #{self.login.dup.color(:green).bright}"
|
82
|
-
i, count = 0, users.count.to_s.color(:green).bright
|
83
|
-
self.transaction do
|
84
|
-
users.each do |user|
|
85
|
-
i += 1
|
86
|
-
u = GitHub::User.find_or_create_by_login(user)
|
87
|
-
self.association(:followers).find_or_create u
|
88
|
-
print "\r#{i.to_s.color(:yellow).bright}/#{count}"
|
89
|
-
end
|
90
|
-
end
|
91
|
-
puts nil
|
92
|
-
self
|
93
|
-
end
|
94
|
-
|
95
|
-
def get_followings
|
96
|
-
users = YAML::load(GitHub::Browser.get "/user/show/#{login}/following")['users'] || []
|
97
|
-
puts "Fetching followings for #{"user".color(:yellow).bright} #{self.login.dup.color(:green).bright}"
|
98
|
-
i, count = 0, users.count.to_s.color(:green).bright
|
99
|
-
self.transaction do
|
100
|
-
users.each do |user|
|
101
|
-
i += 1
|
102
|
-
u = GitHub::User.find_or_create_by_login(user)
|
103
|
-
self.association(:followings).find_or_create u
|
104
|
-
print "\r#{i.to_s.color(:yellow).bright}/#{count}"
|
105
|
-
end
|
106
|
-
end
|
107
|
-
puts nil
|
108
|
-
self
|
109
|
-
end
|
110
|
-
|
111
|
-
def get_organizations
|
112
|
-
organizations = YAML::load(GitHub::Browser.get "/user/show/#{login}/organizations")['organizations'] || []
|
113
|
-
puts "Fetching organizations for #{"user".color(:yellow).bright} #{self.login.dup.color(:green).bright}"
|
114
|
-
i, count = 0, organizations.count.to_s.color(:green).bright
|
115
|
-
self.transaction do
|
116
|
-
organizations.each do |org|
|
117
|
-
i += 1
|
118
|
-
u = GitHub::Organization.find_or_create_by_login(org['login'])
|
119
|
-
self.association(:organizations).find_or_create u
|
120
|
-
print "\r#{i.to_s.color(:yellow).bright}/#{count}"
|
121
|
-
end
|
122
|
-
end
|
123
|
-
puts nil
|
124
|
-
self
|
125
|
-
end
|
126
|
-
|
127
|
-
# Executes when you got a real object
|
128
|
-
# @see GitHub::User#fetch
|
129
|
-
# @return GitHub::User Chainable after mapping followers association
|
130
|
-
def get_repos
|
131
|
-
repos = YAML::load(GitHub::Browser.get "/repos/show/#{login}")['repositories'] || []
|
132
|
-
puts "Fetching repositories for #{"user".color(:yellow).bright} #{self.login.dup.color(:green).bright}"
|
133
|
-
i, count = 0, repos.count.to_s.color(:green).bright
|
134
|
-
self.transaction do
|
135
|
-
repos.each do |repo|
|
136
|
-
i += 1
|
137
|
-
u = GitHub::User.find_or_create_by_login(repo[:owner])
|
138
|
-
r = GitHub::Repo.where(:owner_id => u.id, :name => repo[:name]).first
|
139
|
-
r ||= GitHub::Repo.create(:owner => u, :name => repo[:name])
|
140
|
-
print "\r#{i.to_s.color(:yellow).bright}/#{count}"
|
141
|
-
end
|
142
|
-
end
|
143
|
-
puts nil
|
144
|
-
self
|
145
|
-
end
|
146
|
-
|
147
|
-
public
|
148
|
-
# Returns an array with logins of GitHub::User followers
|
149
|
-
# @param [String] login GitHub login of which followers will be mapped
|
150
|
-
# @return [Array<GitHub::User>] Followers
|
151
|
-
# @deprecated It should not support such way, there should be objects!
|
152
|
-
def self.get_followers(login)
|
153
|
-
users = YAML::load(GitHub::Browser.get "/user/show/#{login}/followers")['users']
|
154
|
-
|
155
|
-
# Loading each user (not effective with 688 followers like schacon has)
|
156
|
-
objects = []
|
157
|
-
i = 1
|
158
|
-
users.each do |user|
|
159
|
-
puts "#{users.length.to_s} / #{i.to_s} - Fetching followers"
|
160
|
-
i = i + 1
|
161
|
-
u = GitHub::User.find_or_create_by_login(user)
|
162
|
-
objects << u
|
163
|
-
end
|
164
|
-
return objects
|
165
|
-
end
|
166
|
-
|
167
|
-
# Collects information from authenticated user.
|
168
|
-
# Used by post requests to authenticate
|
169
|
-
# @return [Hash] Collected from GitHub::User options for HTTP POST request authentication
|
170
|
-
def auth_info
|
171
|
-
{:login => self.login, :token => self.token}
|
172
|
-
end
|
173
|
-
|
174
|
-
# Experimental, sets information about GitHub::User or returns authenticated :self
|
175
|
-
# @param [String] login Login to which post request will be sent
|
176
|
-
# @param [Hash] options Options to include to a post request
|
177
|
-
# @option options [Hash] email 'values[email]' => 'test@api.com' - Sets user email to test@api.com if authenticated
|
178
|
-
# @return [String] Request retrieved data
|
179
|
-
def post(login, options = {})
|
180
|
-
if [:self, :me].include? login
|
181
|
-
login = self.login
|
182
|
-
end
|
183
|
-
return GitHub::Browser.post "/user/show/#{login}", options.merge(self.auth_info)
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|