bucketface 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +32 -0
- data/Rakefile +11 -0
- data/bucketface.gemspec +28 -0
- data/lib/bucketface/client.rb +127 -0
- data/lib/bucketface/repository.rb +28 -0
- data/lib/bucketface/version.rb +3 -0
- data/lib/bucketface.rb +41 -0
- data/test/bucketface_test.rb +137 -0
- data/test/fixtures/branches.json +17 -0
- data/test/fixtures/changeset.json +19 -0
- data/test/fixtures/changesets.json +360 -0
- data/test/fixtures/close_issue.txt +1 -0
- data/test/fixtures/events.json +100 -0
- data/test/fixtures/followers.json +47 -0
- data/test/fixtures/full_user.json +43 -0
- data/test/fixtures/issue.json +22 -0
- data/test/fixtures/issue_followers.json +11 -0
- data/test/fixtures/issues.json +51 -0
- data/test/fixtures/open_issue.json +23 -0
- data/test/fixtures/repo.json +7 -0
- data/test/fixtures/repo_events.json +114 -0
- data/test/fixtures/repo_followers.json +11 -0
- data/test/fixtures/repos.json +17 -0
- data/test/fixtures/tags.json +148 -0
- data/test/fixtures/user.json +17 -0
- data/test/helper.rb +39 -0
- metadata +205 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
bucketface (0.0.1)
|
5
|
+
hashie (~> 0.3.0)
|
6
|
+
httparty (~> 0.6.1)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: http://rubygems.org/
|
10
|
+
specs:
|
11
|
+
crack (0.1.8)
|
12
|
+
fakeweb (1.3.0)
|
13
|
+
hashie (0.3.1)
|
14
|
+
httparty (0.6.1)
|
15
|
+
crack (= 0.1.8)
|
16
|
+
jnunemaker-matchy (0.4.0)
|
17
|
+
mocha (0.9.10)
|
18
|
+
rake
|
19
|
+
rake (0.8.7)
|
20
|
+
shoulda (2.11.3)
|
21
|
+
|
22
|
+
PLATFORMS
|
23
|
+
ruby
|
24
|
+
|
25
|
+
DEPENDENCIES
|
26
|
+
bucketface!
|
27
|
+
fakeweb (~> 1.3)
|
28
|
+
hashie (~> 0.3.0)
|
29
|
+
httparty (~> 0.6.1)
|
30
|
+
jnunemaker-matchy (~> 0.4.0)
|
31
|
+
mocha (~> 0.9)
|
32
|
+
shoulda (~> 2.11)
|
data/Rakefile
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'shoulda/tasks'
|
5
|
+
|
6
|
+
require 'rake/testtask'
|
7
|
+
Rake::TestTask.new(:test) do |test|
|
8
|
+
test.ruby_opts = ["-rubygems"] if defined? Gem
|
9
|
+
test.libs << "lib" << "test"
|
10
|
+
test.pattern = "test/**/*_test.rb"
|
11
|
+
end
|
data/bucketface.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "bucketface/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "bucketface"
|
7
|
+
s.version = Bucketface::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Rafael George"]
|
10
|
+
s.email = ["george.rafael@gmail.com"]
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{Provides a wrapper for Bitbucket API}
|
13
|
+
s.description = %q{Provides a wrapper for Bitbucket API}
|
14
|
+
|
15
|
+
s.rubyforge_project = "bucketface"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_development_dependency('fakeweb', '~> 1.3')
|
23
|
+
s.add_development_dependency('jnunemaker-matchy', '~> 0.4.0')
|
24
|
+
s.add_development_dependency('mocha', '~> 0.9')
|
25
|
+
s.add_development_dependency('shoulda', '~> 2.11')
|
26
|
+
s.add_runtime_dependency('hashie', '~> 0.3.0')
|
27
|
+
s.add_runtime_dependency('httparty', '~> 0.6.1')
|
28
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module Bucketface
|
2
|
+
class Client
|
3
|
+
include HTTParty
|
4
|
+
format :json
|
5
|
+
base_uri "https://api.bitbucket.org/1.0"
|
6
|
+
|
7
|
+
attr_reader :login
|
8
|
+
|
9
|
+
def initialize(auth={})
|
10
|
+
if auth[:password].nil?
|
11
|
+
@login = auth[:login]
|
12
|
+
@token = auth[:token]
|
13
|
+
self.class.basic_auth(nil, nil)
|
14
|
+
else
|
15
|
+
@login = auth[:login]
|
16
|
+
self.class.basic_auth(@login, auth[:password])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def user(login=self.login)
|
21
|
+
get("/users/#{login}/").user
|
22
|
+
end
|
23
|
+
|
24
|
+
def followers(login=self.login)
|
25
|
+
get("/users/#{login}/followers/").followers
|
26
|
+
end
|
27
|
+
|
28
|
+
def repo_followers(repo)
|
29
|
+
repo = Repository.new(repo)
|
30
|
+
get("/repositories/#{repo.user}/#{repo.to_s}/followers/").followers
|
31
|
+
end
|
32
|
+
|
33
|
+
def issue_followers(repo, id)
|
34
|
+
repo = Repository.new(repo)
|
35
|
+
get("/repositories/#{repo.user}/#{repo.to_s}/issues/#{id}/followers/").followers
|
36
|
+
end
|
37
|
+
|
38
|
+
def issues(repo)
|
39
|
+
repo = Repository.new(repo)
|
40
|
+
get("/repositories/#{repo.user}/#{repo.to_s}/issues/").issues
|
41
|
+
end
|
42
|
+
|
43
|
+
def issue(repo, id)
|
44
|
+
repo = Repository.new(repo)
|
45
|
+
get("/repositories/#{repo.user}/#{repo.to_s}/issues/#{id}/")
|
46
|
+
end
|
47
|
+
|
48
|
+
def repo(repo)
|
49
|
+
repo = Repository.new(repo)
|
50
|
+
get("/repositories/#{repo.user}/#{repo.to_s}/")
|
51
|
+
end
|
52
|
+
|
53
|
+
def list_repos(login=self.login)
|
54
|
+
get("/users/#{login}/").repositories
|
55
|
+
end
|
56
|
+
|
57
|
+
def branches(repo)
|
58
|
+
repo = Repository.new(repo)
|
59
|
+
get("/repositories/#{repo.user}/#{repo.to_s}/branches/")
|
60
|
+
end
|
61
|
+
|
62
|
+
def tags(repo)
|
63
|
+
repo = Repository.new(repo)
|
64
|
+
get("/repositories/#{repo.user}/#{repo.to_s}/tags/")
|
65
|
+
end
|
66
|
+
|
67
|
+
def open_issue(repo, title, body)
|
68
|
+
rep = Repository.new(repo)
|
69
|
+
post("/repositories/#{rep.user}/#{rep.to_s}/issues/", :body => {:title => title, :content => body})
|
70
|
+
end
|
71
|
+
|
72
|
+
def close_issue(repo, id)
|
73
|
+
repo = Repository.new(repo)
|
74
|
+
delete("/repositories/#{repo.user}/#{repo.to_s}/issues/#{id}/")
|
75
|
+
end
|
76
|
+
|
77
|
+
def changesets(repo)
|
78
|
+
repo = Repository.new(repo)
|
79
|
+
get_resource("/repositories/#{repo.user}/#{repo.to_s}/changesets/").changesets
|
80
|
+
end
|
81
|
+
|
82
|
+
def changeset(repo, changeset)
|
83
|
+
repo = Repository.new(repo)
|
84
|
+
get("/repositories/#{repo.user}/#{repo.to_s}/changesets/#{changeset}/")
|
85
|
+
end
|
86
|
+
|
87
|
+
def events(login=self.login)
|
88
|
+
get("/users/#{login}/events/").events
|
89
|
+
end
|
90
|
+
|
91
|
+
def repo_events(repo)
|
92
|
+
repo = Repository.new(repo)
|
93
|
+
get("/repositories/#{repo.user}/#{repo.to_s}/events/").events
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
def get(path, options = {})
|
98
|
+
Hashie::Mash.new(self.class.get(path, options))
|
99
|
+
end
|
100
|
+
|
101
|
+
def post(path, options = {})
|
102
|
+
Hashie::Mash.new(self.class.post(path, options))
|
103
|
+
end
|
104
|
+
|
105
|
+
def delete(path, options = {})
|
106
|
+
self.class.delete(path, options)
|
107
|
+
end
|
108
|
+
|
109
|
+
def get_resource(path, options ={})
|
110
|
+
get(path, {:query => options})
|
111
|
+
end
|
112
|
+
|
113
|
+
def post_resource(path, options = {})
|
114
|
+
post(path, options)
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.delete(*args); handle_response super end
|
118
|
+
|
119
|
+
def self.handle_response(response)
|
120
|
+
case response.code
|
121
|
+
when 204 then return "Success!"
|
122
|
+
else
|
123
|
+
response
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Bucketface
|
2
|
+
class Repository
|
3
|
+
attr_accessor :username, :name
|
4
|
+
|
5
|
+
def initialize(repo)
|
6
|
+
case repo
|
7
|
+
when String
|
8
|
+
repo = repo.split("/")
|
9
|
+
@name = repo.pop
|
10
|
+
@username = repo.pop
|
11
|
+
when Repository
|
12
|
+
@username = repo.username
|
13
|
+
@name = repo.name
|
14
|
+
when Hash
|
15
|
+
@name = repo[:repo] ||= repo[:name]
|
16
|
+
@username = repo[:username] ||= repo[:user]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def user
|
21
|
+
@username
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
@name
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/bucketface.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
require 'httparty'
|
4
|
+
require 'hashie'
|
5
|
+
Hash.send :include, Hashie::HashExtensions
|
6
|
+
|
7
|
+
libdir = File.dirname(__FILE__)
|
8
|
+
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
9
|
+
|
10
|
+
require 'bucketface/repository'
|
11
|
+
require 'bucketface/client'
|
12
|
+
|
13
|
+
module Bucketface
|
14
|
+
extend SingleForwardable
|
15
|
+
|
16
|
+
class BucketfaceError < StandardError
|
17
|
+
attr_reader :data
|
18
|
+
|
19
|
+
def initialize(data)
|
20
|
+
@data = data
|
21
|
+
super
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.client; Client.new end
|
26
|
+
|
27
|
+
# Users
|
28
|
+
def_delegators :client, :user, :followers
|
29
|
+
|
30
|
+
# Repositories
|
31
|
+
def_delegators :client, :repo_followers, :repo, :list_repos, :branches, :tags
|
32
|
+
|
33
|
+
# Issues
|
34
|
+
def_delegators :client, :issue_followers, :issues, :issue
|
35
|
+
|
36
|
+
# Changesets
|
37
|
+
def_delegators :client, :changesets, :changeset
|
38
|
+
|
39
|
+
# Events
|
40
|
+
def_delegators :client, :events, :repo_events
|
41
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)) + '/helper'
|
2
|
+
|
3
|
+
class BucketfaceTest < Test::Unit::TestCase
|
4
|
+
context "when authenticated" do
|
5
|
+
setup do
|
6
|
+
@client = Bucketface::Client.new(:login => 'cored', :token => '2U812')
|
7
|
+
end
|
8
|
+
|
9
|
+
should "authenticate via basic auth" do
|
10
|
+
stub_get('https://cored:2U812@api.bitbucket.org/1.0/users/cored/?', 'full_user.json')
|
11
|
+
client = Bucketface::Client.new(:login => 'cored', :password => '2U812')
|
12
|
+
user = client.user
|
13
|
+
user.is_private?.should == false
|
14
|
+
end
|
15
|
+
|
16
|
+
should "return followers for an user authenticated user" do
|
17
|
+
stub_get('/users/cored/followers/?', 'followers.json')
|
18
|
+
followers = @client.followers
|
19
|
+
followers.size.should == 3
|
20
|
+
end
|
21
|
+
|
22
|
+
should "open an issue" do
|
23
|
+
stub_post('/repositories/cored/test-repo/issues/', 'open_issue.json')
|
24
|
+
issue = @client.open_issue({:username => 'cored', :repo => 'test-repo'}, "testing", "testing")
|
25
|
+
issue.title.should == "new issue"
|
26
|
+
end
|
27
|
+
|
28
|
+
should "delete an issue" do
|
29
|
+
stub_delete('/repositories/cored/test-repo/issues/1/', 'close_issue.txt')
|
30
|
+
issue = @client.close_issue({:username => 'cored', :repo => 'test-repo'}, 1)
|
31
|
+
issue.should == "Success!"
|
32
|
+
end
|
33
|
+
|
34
|
+
should "update an issue"
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
context "user resource" do
|
39
|
+
should "return user info" do
|
40
|
+
stub_get("/users/cored/", "user.json")
|
41
|
+
user = Bucketface.user("cored")
|
42
|
+
user.username.should == 'cored'
|
43
|
+
end
|
44
|
+
|
45
|
+
should "return followers for a user" do
|
46
|
+
stub_get("/users/cored/followers/", "followers.json")
|
47
|
+
followers = Bucketface.followers("cored")
|
48
|
+
followers.size.should == 3
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "changeset resource" do
|
53
|
+
should "return a list of changeset for a giving repository" do
|
54
|
+
stub_get("/repositories/cored/test-repo/changesets/", "changesets.json")
|
55
|
+
changesets = Bucketface.changesets(:username => 'cored', :repo => 'test-repo')
|
56
|
+
changesets.size.should == 15
|
57
|
+
end
|
58
|
+
|
59
|
+
should "return an specific changeset for a giving repository" do
|
60
|
+
stub_get("/repositories/cored/test-repo/changesets/fa57572a9acf/", "changeset.json")
|
61
|
+
changeset = Bucketface.changeset({:username => 'cored', :repo => 'test-repo'}, 'fa57572a9acf')
|
62
|
+
changeset.author.should == 'jespern'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "events resource" do
|
67
|
+
should "return a list of events for a giving user" do
|
68
|
+
stub_get("/users/cored/events/", "events.json")
|
69
|
+
events = Bucketface.events('cored')
|
70
|
+
events.size.should == 5
|
71
|
+
events.first.repository.slug.should == 'test-repo'
|
72
|
+
end
|
73
|
+
|
74
|
+
should "return a list of events for a giving repository" do
|
75
|
+
stub_get("/repositories/cored/test-repo/events/", "repo_events.json")
|
76
|
+
events = Bucketface.repo_events(:username => 'cored', :repo => 'test-repo')
|
77
|
+
events.size.should == 6
|
78
|
+
events.first.repository.slug == 'test-repo'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "repository resource" do
|
83
|
+
should "return list of followers for a giving repository" do
|
84
|
+
stub_get("/repositories/cored/test-repo/followers/", "repo_followers.json")
|
85
|
+
repo_followers = Bucketface.repo_followers({:user => "cored", :repo => "test-repo"})
|
86
|
+
repo_followers.size.should == 1
|
87
|
+
end
|
88
|
+
|
89
|
+
should "return repository info" do
|
90
|
+
stub_get("/repositories/cored/test-repo/", "repo.json")
|
91
|
+
repo = Bucketface.repo(:user => "cored", :repo => "test-repo")
|
92
|
+
repo.name.should == "test-repo"
|
93
|
+
end
|
94
|
+
|
95
|
+
should "list repositories for an user" do
|
96
|
+
stub_get("/users/cored/", "repos.json")
|
97
|
+
repos = Bucketface.list_repos("cored")
|
98
|
+
repos.first.name.should == "test-repo"
|
99
|
+
end
|
100
|
+
|
101
|
+
should "list branches in a giving repo" do
|
102
|
+
stub_get("/repositories/cored/test-repo/branches/", "branches.json")
|
103
|
+
branches = Bucketface.branches(:user => "cored", :repo => "test-repo")
|
104
|
+
branches.size.should == 1
|
105
|
+
assert branches.include?("default")
|
106
|
+
end
|
107
|
+
|
108
|
+
should "list all the tags in a giving repo" do
|
109
|
+
stub_get("/repositories/cored/test-repo/tags/", "tags.json")
|
110
|
+
tags = Bucketface.tags(:user => "cored", :repo => "test-repo")
|
111
|
+
tags.size.should == 6
|
112
|
+
assert tags.include?("0.6.4")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context "issue resource" do
|
117
|
+
should "return the list of followers of an issue" do
|
118
|
+
stub_get("/repositories/cored/test-repo/issues/1/followers/", "issue_followers.json")
|
119
|
+
issue_followers = Bucketface.issue_followers({:user => "cored", :repo => "test-repo"},"1")
|
120
|
+
issue_followers.size.should == 1
|
121
|
+
end
|
122
|
+
|
123
|
+
should "return the list of issues for a giving repository" do
|
124
|
+
stub_get("/repositories/cored/test-repo/issues/", "issues.json")
|
125
|
+
issues = Bucketface.issues({:user => "cored", :repo => "test-repo"})
|
126
|
+
issues.size.should == 2
|
127
|
+
issues.first.title.should == "Another issue test"
|
128
|
+
end
|
129
|
+
|
130
|
+
should "return an individual issue" do
|
131
|
+
stub_get("/repositories/cored/test-repo/issues/1/", "issue.json")
|
132
|
+
issue = Bucketface.issue({:user => "cored", :repo => "test-repo"}, "1")
|
133
|
+
issue.title.should == "Test issue"
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
{
|
2
|
+
"default": {
|
3
|
+
"node": "10c1068f1171",
|
4
|
+
"files": [],
|
5
|
+
"author": "elpargo",
|
6
|
+
"timestamp": "2009-08-26 17:11:33",
|
7
|
+
"raw_node": "10c1068f117163e7c3e98d2a461799481367b727",
|
8
|
+
"parents": [
|
9
|
+
"041529d47395",
|
10
|
+
"b119fb3263f7"
|
11
|
+
],
|
12
|
+
"branch": "default",
|
13
|
+
"message": "- merging",
|
14
|
+
"revision": 132,
|
15
|
+
"size": 0
|
16
|
+
}
|
17
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
{
|
2
|
+
"node": "fa57572a9acf",
|
3
|
+
"files": [
|
4
|
+
{
|
5
|
+
"type": "modified",
|
6
|
+
"file": "piston/handler.py"
|
7
|
+
}
|
8
|
+
],
|
9
|
+
"author": "jespern",
|
10
|
+
"timestamp": "2009-09-09 12:55:07",
|
11
|
+
"raw_node": "fa57572a9acf7b66aa66f739af6d1391075f9f21",
|
12
|
+
"parents": [
|
13
|
+
"aaf0c2d64294"
|
14
|
+
],
|
15
|
+
"branch": "default",
|
16
|
+
"message": "warning in case of a model being registered twice under different handlers, configurable via PISTON_IGNORE_DUPE_MODELS",
|
17
|
+
"revision": 207,
|
18
|
+
"size": 561
|
19
|
+
}
|