octopi 0.1.0 → 0.2.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.
- data/.gitignore +2 -1
- data/.yardoc +0 -0
- data/README.rdoc +16 -41
- data/Rakefile +9 -0
- data/VERSION.yml +2 -2
- data/examples/overall.rb +1 -1
- data/lib/ext/hash_ext.rb +5 -0
- data/lib/ext/string_ext.rb +5 -0
- data/lib/octopi.rb +101 -202
- data/lib/octopi/api.rb +209 -0
- data/lib/octopi/base.rb +42 -38
- data/lib/octopi/blob.rb +12 -8
- data/lib/octopi/branch.rb +20 -7
- data/lib/octopi/branch_set.rb +11 -0
- data/lib/octopi/comment.rb +20 -0
- data/lib/octopi/commit.rb +39 -35
- data/lib/octopi/error.rb +17 -5
- data/lib/octopi/file_object.rb +6 -5
- data/lib/octopi/gist.rb +28 -0
- data/lib/octopi/issue.rb +49 -40
- data/lib/octopi/issue_comment.rb +7 -0
- data/lib/octopi/issue_set.rb +21 -0
- data/lib/octopi/key.rb +14 -7
- data/lib/octopi/key_set.rb +14 -0
- data/lib/octopi/plan.rb +5 -0
- data/lib/octopi/repository.rb +66 -45
- data/lib/octopi/repository_set.rb +9 -0
- data/lib/octopi/resource.rb +11 -16
- data/lib/octopi/self.rb +33 -0
- data/lib/octopi/tag.rb +12 -6
- data/lib/octopi/user.rb +62 -38
- data/octopi.gemspec +43 -12
- data/test/api_test.rb +58 -0
- data/test/authenticated_test.rb +39 -0
- data/test/blob_test.rb +23 -0
- data/test/branch_test.rb +20 -0
- data/test/commit_test.rb +82 -0
- data/test/file_object_test.rb +39 -0
- data/test/gist_test.rb +16 -0
- data/test/issue_comment.rb +19 -0
- data/test/issue_set_test.rb +33 -0
- data/test/issue_test.rb +120 -0
- data/test/key_set_test.rb +29 -0
- data/test/key_test.rb +35 -0
- data/test/repository_set_test.rb +23 -0
- data/test/repository_test.rb +141 -0
- data/test/stubs/commits/fcoury/octopi/octopi.rb +818 -0
- data/test/tag_test.rb +20 -0
- data/test/test_helper.rb +236 -0
- data/test/user_test.rb +92 -0
- metadata +54 -12
- data/examples/github.yml.example +0 -14
- data/test/octopi_test.rb +0 -46
data/lib/octopi/resource.rb
CHANGED
@@ -37,30 +37,25 @@ module Octopi
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def find(*args)
|
40
|
-
api = args.last.is_a?(Api) ? args.pop : ANONYMOUS_API
|
41
40
|
args = args.join('/') if args.is_a? Array
|
42
|
-
result = api.find(path_for(:resource), @resource_name[:singular], args)
|
41
|
+
result = Api.api.find(path_for(:resource), @resource_name[:singular], args, self, @cache)
|
43
42
|
key = result.keys.first
|
44
43
|
|
45
44
|
if result[key].is_a? Array
|
46
|
-
result[key].map { |r| new(
|
47
|
-
else
|
48
|
-
Resource.for(key).new(
|
49
|
-
end
|
45
|
+
result[key].map { |r| new(r) }
|
46
|
+
else
|
47
|
+
Resource.for(key).new(result[key])
|
48
|
+
end
|
50
49
|
end
|
51
|
-
|
50
|
+
|
52
51
|
def find_all(*s)
|
53
|
-
|
54
|
-
find_plural(s, :find, api)
|
52
|
+
find_plural(s, :find)
|
55
53
|
end
|
56
|
-
|
57
|
-
def find_plural(s, path
|
54
|
+
|
55
|
+
def find_plural(s, path)
|
58
56
|
s = s.join('/') if s.is_a? Array
|
59
|
-
api.find_all(path_for(path), @resource_name[:plural], s)
|
60
|
-
|
61
|
-
payload = block_given? ? yield(item) : item
|
62
|
-
new(api, payload)
|
63
|
-
end
|
57
|
+
resources = Api.api.find_all(path_for(path), @resource_name[:plural], s, self)
|
58
|
+
resources.map { |item| self.new(item) }
|
64
59
|
end
|
65
60
|
|
66
61
|
def declassify(s)
|
data/lib/octopi/self.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Octopi
|
2
|
+
module Self
|
3
|
+
# Returns a list of Key objects containing all SSH Public Keys this user
|
4
|
+
# currently has. Requires authentication.
|
5
|
+
def keys
|
6
|
+
raise AuthenticationRequired, "To view keys, you must be authenticated" if Api.api.read_only?
|
7
|
+
result = Api.api.get("/user/keys", { :cache => false })
|
8
|
+
return unless result and result["public_keys"]
|
9
|
+
KeySet.new(result["public_keys"].inject([]) { |result, element| result << Key.new(element) })
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns a list of Email objects containing the email addresses associated with this user.
|
13
|
+
# Requires authentication.
|
14
|
+
def emails
|
15
|
+
raise AuthenticationRequired, "To view emails, you must be authenticated" if Api.api.read_only?
|
16
|
+
get("/user/emails")['emails']
|
17
|
+
end
|
18
|
+
|
19
|
+
# Start following a user.
|
20
|
+
# Can only be called if you are authenticated.
|
21
|
+
def follow!(login)
|
22
|
+
raise AuthenticationRequired, "To begin following someone, you must be authenticated" if Api.api.read_only?
|
23
|
+
Api.api.post("/user/follow/#{login}")
|
24
|
+
end
|
25
|
+
|
26
|
+
# Stop following a user.
|
27
|
+
# Can only be called if you are authenticated.
|
28
|
+
def unfollow!(login)
|
29
|
+
raise AuthenticationRequired, "To stop following someone, you must be authenticated" if Api.api.read_only?
|
30
|
+
Api.api.post("/user/unfollow/#{login}")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/octopi/tag.rb
CHANGED
@@ -1,17 +1,23 @@
|
|
1
1
|
module Octopi
|
2
2
|
class Tag < Base
|
3
3
|
include Resource
|
4
|
+
|
5
|
+
attr_accessor :name, :sha
|
4
6
|
set_resource_name "tag"
|
5
7
|
|
6
8
|
resource_path "/repos/show/:id"
|
7
9
|
|
8
|
-
def
|
9
|
-
|
10
|
-
|
10
|
+
def initialize(*args)
|
11
|
+
args = args.flatten!
|
12
|
+
self.name = args.first
|
13
|
+
self.sha = args.last
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.all(options={})
|
17
|
+
ensure_hash(options)
|
18
|
+
user, repo = gather_details(options)
|
11
19
|
self.validate_args(user => :user, repo => :repo)
|
12
|
-
find_plural([user,repo,'tags'], :resource){
|
13
|
-
|i| {:name => i.first, :hash => i.last }
|
14
|
-
}
|
20
|
+
find_plural([user, repo, 'tags'], :resource) { |i| Tag.new(i) }
|
15
21
|
end
|
16
22
|
end
|
17
23
|
end
|
data/lib/octopi/user.rb
CHANGED
@@ -1,10 +1,17 @@
|
|
1
1
|
module Octopi
|
2
2
|
class User < Base
|
3
3
|
include Resource
|
4
|
+
attr_accessor :company, :name, :following_count, :blog, :public_repo_count, :public_gist_count, :id, :login, :followers_count, :created_at, :email, :location, :disk_usage, :private_repo_count, :private_gist_count, :collaborators, :plan, :owned_private_repo_count, :total_private_repo_count,
|
5
|
+
# These come from search results, which doesn't contain the above information.
|
6
|
+
:actions, :score, :language, :followers, :following, :fullname, :type, :username, :repos, :pushed, :created
|
7
|
+
|
8
|
+
def plan=(attributes={})
|
9
|
+
@plan = Plan.new(attributes)
|
10
|
+
end
|
4
11
|
|
5
12
|
find_path "/user/search/:query"
|
6
13
|
resource_path "/user/show/:id"
|
7
|
-
|
14
|
+
|
8
15
|
# Finds a single user identified by the given username
|
9
16
|
#
|
10
17
|
# Example:
|
@@ -26,6 +33,10 @@ module Octopi
|
|
26
33
|
self.validate_args(username => :user)
|
27
34
|
super username
|
28
35
|
end
|
36
|
+
|
37
|
+
class << self
|
38
|
+
alias_method :search, :find_all
|
39
|
+
end
|
29
40
|
|
30
41
|
# Returns a collection of Repository objects, containing
|
31
42
|
# all repositories of the user.
|
@@ -34,58 +45,70 @@ module Octopi
|
|
34
45
|
# additional information will be provided for the
|
35
46
|
# Repositories.
|
36
47
|
def repositories
|
37
|
-
|
38
|
-
|
48
|
+
rs = RepositorySet.new(Repository.find(:user => self.login))
|
49
|
+
rs.user = self
|
50
|
+
rs
|
39
51
|
end
|
40
52
|
|
41
|
-
# Searches for user Repository identified by
|
42
|
-
|
43
|
-
|
44
|
-
self.class.
|
45
|
-
Repository.find(login
|
53
|
+
# Searches for user Repository identified by name
|
54
|
+
def repository(options={})
|
55
|
+
options = { :name => options } if options.is_a?(String)
|
56
|
+
self.class.ensure_hash(options)
|
57
|
+
Repository.find({ :user => login }.merge!(options))
|
46
58
|
end
|
47
59
|
|
48
|
-
def create_repository(name,
|
60
|
+
def create_repository(name, options = {})
|
49
61
|
self.class.validate_args(name => :repo)
|
50
|
-
Repository.create(self, name,
|
62
|
+
Repository.create(self, name, options)
|
63
|
+
end
|
64
|
+
|
65
|
+
def watching
|
66
|
+
repositories = []
|
67
|
+
Api.api.get("/repos/watched/#{login}")["repositories"].each do |repo|
|
68
|
+
repositories << Repository.new(repo)
|
69
|
+
end
|
70
|
+
repositories
|
51
71
|
end
|
52
72
|
|
53
|
-
# Adds an SSH Public Key to the user. Requires
|
54
|
-
# authentication.
|
55
|
-
def add_key(title, key)
|
56
|
-
raise APIError,
|
57
|
-
"To add a key, you must be authenticated" if @api.read_only?
|
58
73
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
Key.new(@api, key_params.first, self)
|
74
|
+
# Gets a list of followers.
|
75
|
+
# Returns an array of logins.
|
76
|
+
def followers
|
77
|
+
user_property("followers")
|
64
78
|
end
|
65
79
|
|
66
|
-
#
|
67
|
-
#
|
68
|
-
|
69
|
-
|
70
|
-
|
80
|
+
# Gets a list of followers.
|
81
|
+
# Returns an array of user objects.
|
82
|
+
# If user has a large number of followers you may be rate limited by the API.
|
83
|
+
def followers!
|
84
|
+
user_property("followers", true)
|
85
|
+
end
|
71
86
|
|
72
|
-
|
73
|
-
|
74
|
-
|
87
|
+
# Gets a list of people this user is following.
|
88
|
+
# Returns an array of logins.
|
89
|
+
def following
|
90
|
+
user_property("following")
|
75
91
|
end
|
92
|
+
|
93
|
+
# Gets a list of people this user is following.
|
94
|
+
# Returns an array of user objectrs.
|
95
|
+
# If user has a large number of people whom they follow, you may be rate limited by the API.
|
96
|
+
def following!
|
97
|
+
user_property("following", true)
|
98
|
+
end
|
99
|
+
|
76
100
|
|
77
|
-
#
|
78
|
-
#
|
79
|
-
|
80
|
-
|
81
|
-
user_property(method, false)
|
82
|
-
end
|
83
|
-
define_method("#{method}!") do
|
84
|
-
user_property(method, true)
|
85
|
-
end
|
101
|
+
# If a user object is passed into a method, we can use this.
|
102
|
+
# It'll also work if we pass in just the login.
|
103
|
+
def to_s
|
104
|
+
login
|
86
105
|
end
|
87
106
|
|
88
|
-
|
107
|
+
private
|
108
|
+
|
109
|
+
# Helper method for "deep" finds.
|
110
|
+
# Determines whether to return an array of logins (light) or user objects (heavy).
|
111
|
+
def user_property(property, deep=false)
|
89
112
|
users = []
|
90
113
|
property(property, login).each_pair do |k,v|
|
91
114
|
return v unless deep
|
@@ -95,5 +118,6 @@ module Octopi
|
|
95
118
|
|
96
119
|
users
|
97
120
|
end
|
121
|
+
|
98
122
|
end
|
99
123
|
end
|
data/octopi.gemspec
CHANGED
@@ -1,12 +1,15 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
1
4
|
# -*- encoding: utf-8 -*-
|
2
5
|
|
3
6
|
Gem::Specification.new do |s|
|
4
7
|
s.name = %q{octopi}
|
5
|
-
s.version = "0.1
|
8
|
+
s.version = "0.2.1"
|
6
9
|
|
7
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
11
|
s.authors = ["Felipe Coury"]
|
9
|
-
s.date = %q{2009-
|
12
|
+
s.date = %q{2009-11-10}
|
10
13
|
s.email = %q{felipe.coury@gmail.com}
|
11
14
|
s.extra_rdoc_files = [
|
12
15
|
"LICENSE",
|
@@ -14,42 +17,64 @@ Gem::Specification.new do |s|
|
|
14
17
|
]
|
15
18
|
s.files = [
|
16
19
|
".gitignore",
|
20
|
+
".yardoc",
|
17
21
|
"LICENSE",
|
18
22
|
"README.rdoc",
|
19
23
|
"Rakefile",
|
20
24
|
"VERSION.yml",
|
21
25
|
"contrib/backup.rb",
|
22
|
-
"
|
23
|
-
"
|
24
|
-
"examples/issues.rb",
|
25
|
-
"examples/overall.rb",
|
26
|
+
"lib/ext/hash_ext.rb",
|
27
|
+
"lib/ext/string_ext.rb",
|
26
28
|
"lib/octopi.rb",
|
29
|
+
"lib/octopi/api.rb",
|
27
30
|
"lib/octopi/base.rb",
|
28
31
|
"lib/octopi/blob.rb",
|
29
32
|
"lib/octopi/branch.rb",
|
33
|
+
"lib/octopi/branch_set.rb",
|
34
|
+
"lib/octopi/comment.rb",
|
30
35
|
"lib/octopi/commit.rb",
|
31
36
|
"lib/octopi/error.rb",
|
32
37
|
"lib/octopi/file_object.rb",
|
38
|
+
"lib/octopi/gist.rb",
|
33
39
|
"lib/octopi/issue.rb",
|
40
|
+
"lib/octopi/issue_comment.rb",
|
41
|
+
"lib/octopi/issue_set.rb",
|
34
42
|
"lib/octopi/key.rb",
|
43
|
+
"lib/octopi/key_set.rb",
|
44
|
+
"lib/octopi/plan.rb",
|
35
45
|
"lib/octopi/repository.rb",
|
46
|
+
"lib/octopi/repository_set.rb",
|
36
47
|
"lib/octopi/resource.rb",
|
48
|
+
"lib/octopi/self.rb",
|
37
49
|
"lib/octopi/tag.rb",
|
38
50
|
"lib/octopi/user.rb",
|
39
|
-
"octopi.gemspec"
|
40
|
-
"test/octopi_test.rb",
|
41
|
-
"test/test_helper.rb"
|
51
|
+
"octopi.gemspec"
|
42
52
|
]
|
43
|
-
s.has_rdoc = true
|
44
53
|
s.homepage = %q{http://github.com/fcoury/octopi}
|
45
54
|
s.rdoc_options = ["--charset=UTF-8"]
|
46
55
|
s.require_paths = ["lib"]
|
47
56
|
s.rubyforge_project = %q{octopi}
|
48
|
-
s.rubygems_version = %q{1.3.
|
57
|
+
s.rubygems_version = %q{1.3.5}
|
49
58
|
s.summary = %q{A Ruby interface to GitHub API v2}
|
50
59
|
s.test_files = [
|
51
|
-
"test/
|
60
|
+
"test/api_test.rb",
|
61
|
+
"test/authenticated_test.rb",
|
62
|
+
"test/blob_test.rb",
|
63
|
+
"test/branch_test.rb",
|
64
|
+
"test/commit_test.rb",
|
65
|
+
"test/file_object_test.rb",
|
66
|
+
"test/gist_test.rb",
|
67
|
+
"test/issue_comment.rb",
|
68
|
+
"test/issue_set_test.rb",
|
69
|
+
"test/issue_test.rb",
|
70
|
+
"test/key_set_test.rb",
|
71
|
+
"test/key_test.rb",
|
72
|
+
"test/repository_set_test.rb",
|
73
|
+
"test/repository_test.rb",
|
74
|
+
"test/stubs/commits/fcoury/octopi/octopi.rb",
|
75
|
+
"test/tag_test.rb",
|
52
76
|
"test/test_helper.rb",
|
77
|
+
"test/user_test.rb",
|
53
78
|
"examples/authenticated.rb",
|
54
79
|
"examples/issues.rb",
|
55
80
|
"examples/overall.rb"
|
@@ -60,8 +85,14 @@ Gem::Specification.new do |s|
|
|
60
85
|
s.specification_version = 3
|
61
86
|
|
62
87
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
88
|
+
s.add_runtime_dependency(%q<nokogiri>, [">= 1.3.1"])
|
89
|
+
s.add_runtime_dependency(%q<httparty>, [">= 0.4.5"])
|
63
90
|
else
|
91
|
+
s.add_dependency(%q<nokogiri>, [">= 1.3.1"])
|
92
|
+
s.add_dependency(%q<httparty>, [">= 0.4.5"])
|
64
93
|
end
|
65
94
|
else
|
95
|
+
s.add_dependency(%q<nokogiri>, [">= 1.3.1"])
|
96
|
+
s.add_dependency(%q<httparty>, [">= 0.4.5"])
|
66
97
|
end
|
67
98
|
end
|
data/test/api_test.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
class AuthenticatedTest < Test::Unit::TestCase
|
4
|
+
include Octopi
|
5
|
+
|
6
|
+
def setup
|
7
|
+
fake_everything
|
8
|
+
@user = User.find("fcoury")
|
9
|
+
end
|
10
|
+
|
11
|
+
context "following" do
|
12
|
+
|
13
|
+
should "not be able to follow anyone if not authenticated" do
|
14
|
+
exception = assert_raise AuthenticationRequired do
|
15
|
+
Api.me.follow!("rails")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
should "be able to follow a user" do
|
20
|
+
auth do
|
21
|
+
assert_not_nil Api.me.follow!("rails")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "unfollowing" do
|
27
|
+
|
28
|
+
should "not be able to follow anyone if not authenticated" do
|
29
|
+
exception = assert_raise AuthenticationRequired do
|
30
|
+
Api.me.unfollow!("rails")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
should "be able to follow a user" do
|
35
|
+
auth do
|
36
|
+
assert_not_nil Api.me.unfollow!("rails")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "keys" do
|
42
|
+
should "not be able to see keys if not authenticated" do
|
43
|
+
exception = assert_raise AuthenticationRequired do
|
44
|
+
Api.me.keys
|
45
|
+
end
|
46
|
+
|
47
|
+
assert_equal "To view keys, you must be authenticated", exception.message
|
48
|
+
end
|
49
|
+
|
50
|
+
should "have some keys" do
|
51
|
+
auth do
|
52
|
+
keys = Api.me.keys
|
53
|
+
assert keys.is_a?(KeySet)
|
54
|
+
assert_equal 2, keys.size
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
class AuthenticatedTest < Test::Unit::TestCase
|
4
|
+
include Octopi
|
5
|
+
def setup
|
6
|
+
fake_everything
|
7
|
+
end
|
8
|
+
|
9
|
+
context "Authenticating" do
|
10
|
+
should "be possible with username and password" do
|
11
|
+
authenticated_with(:login => "fcoury", :password => "yruocf") do
|
12
|
+
assert_equal "8f700e0d7747826f3e56ee13651414bd", Api.api.token
|
13
|
+
assert_not_nil User.find("fcoury")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
should "be possible with username and token" do
|
18
|
+
auth do
|
19
|
+
assert_not_nil User.find("fcoury")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
should "be possible using the .gitconfig" do
|
24
|
+
authenticated do
|
25
|
+
assert_not_nil User.find("fcoury")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
#
|
29
|
+
# should "be denied access when specifying an invalid token and login combination" do
|
30
|
+
# FakeWeb.clean_registry
|
31
|
+
# FakeWeb.register_uri(:get, "http://github.com/api/v2/yaml/user/show/fcoury", :status => ["404", "Not Found"])
|
32
|
+
# assert_raise InvalidLogin do
|
33
|
+
# authenticated_with :login => "fcoury", :token => "ba7bf2d7f0ebc073d3874dda887b18ae" do
|
34
|
+
# # Just blank will do us fine.
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
end
|
39
|
+
end
|