6
6
from ..service import register_target , RepositoryService
7
7
from ...exceptions import ResourceError , ResourceExistsError , ResourceNotFoundError
8
8
9
- import bitbucket .bitbucket as bitbucket
9
+ from pybitbucket .bitbucket import Client
10
+ from pybitbucket .auth import BasicAuthenticator
11
+ from pybitbucket .user import User
12
+ from pybitbucket .repository import Repository , RepositoryForkPolicy
13
+
10
14
from requests import Request , Session
15
+ from requests .exceptions import HTTPError
11
16
import json
12
17
13
- '''
14
- Extension of the bitbucket module implementation to add support for the extra
15
- features the original implementation lacked. This is a temporary measure, up
16
- until a PR is crafted for the original code.
17
- '''
18
-
19
- bitbucket .URLS .update ({
20
- 'GET_REPO' : 'repositories/%(username)s/%(repo_slug)s/' ,
21
- 'DELETE_REPO' : 'repositories/%(accountname)s/%(repo_slug)s' ,
22
- 'FORK_REPO' : 'repositories/%(username)s/%(repo_slug)s/fork' ,
23
- })
24
-
25
- class Bitbucket (bitbucket .Bitbucket ):
26
- def __init__ (self , * args , ** kwarg ):
27
- super (Bitbucket , self ).__init__ (self )
28
- self .session = Session ()
29
- # XXX monkey patching of requests within bitbucket module
30
- self .requests = self .session
31
-
32
- def get (self , user = None , repo_slug = None ):
33
- """ Get a single repository on Bitbucket and return it."""
34
- username = user or self .username
35
- repo_slug = repo_slug or self .repo_slug or ''
36
- url = self .url ('GET_REPO' , username = username , repo_slug = repo_slug )
37
- return self .dispatch ('GET' , url , auth = self .auth )
38
-
39
- def delete (self , user , repo_slug ):
40
- url = self .url ('DELETE_REPO' , username = user , accountname = user , repo_slug = repo_slug )
41
- return self .dispatch ('DELETE' , url , auth = self .auth )
42
-
43
- def fork (self , user , repo_slug , new_name = None ):
44
- url = self .url ('FORK_REPO' , username = user , repo_slug = repo_slug )
45
- new_repo = new_name or repo_slug
46
- return self .dispatch ('POST' , url , name = new_repo , auth = self .auth )
47
-
48
- def dispatch (self , method , url , auth = None , params = None , ** kwargs ):
49
- """ Send HTTP request, with given method,
50
- credentials and data to the given URL,
51
- and return the success and the result on success.
52
- """
53
- r = Request (
54
- method = method ,
55
- url = url ,
56
- auth = auth ,
57
- params = params ,
58
- data = kwargs )
59
- resp = self .session .send (r .prepare ())
60
- status = resp .status_code
61
- text = resp .text
62
- error = resp .reason
63
- if status >= 200 and status < 300 :
64
- if text :
65
- try :
66
- return (True , json .loads (text ))
67
- except TypeError :
68
- pass
69
- except ValueError :
70
- pass
71
- return (True , text )
72
- elif status >= 300 and status < 400 :
73
- return (
74
- False ,
75
- 'Unauthorized access, '
76
- 'please check your credentials.' )
77
- elif status == 404 :
78
- return (False , dict (message = 'Service not found' , reason = error , code = status ))
79
- elif status == 400 :
80
- return (False , dict (message = 'Bad request sent to server.' , reason = error , code = status ))
81
- elif status == 401 :
82
- return (False , dict (message = 'Not enough privileges.' , reason = error , code = status ))
83
- elif status == 403 :
84
- return (False , dict (message = 'Not authorized.' , reason = error , code = status ))
85
- elif status == 402 or status >= 405 :
86
- return (False , dict (message = 'Request error.' , reason = error , code = status ))
87
- elif status >= 500 and status < 600 :
88
- return (False , dict (message = 'Server error.' , reason = error , code = status ))
89
- else :
90
- return (False , dict (message = 'Unidentified error.' , reason = error , code = status ))
18
+ # bitbucket.URLS.update({
19
+ # 'GET_REPO' : 'repositories/%(username)s/%(repo_slug)s/',
20
+ # 'DELETE_REPO' : 'repositories/%(accountname)s/%(repo_slug)s',
21
+ # 'FORK_REPO' : 'repositories/%(username)s/%(repo_slug)s/fork',
22
+ # })
91
23
92
24
93
25
@register_target ('bb' , 'bitbucket' )
94
26
class BitbucketService (RepositoryService ):
95
27
fqdn = 'bitbucket.org'
96
28
97
29
def __init__ (self , * args , ** kwarg ):
98
- self .bb = Bitbucket ()
30
+ self .bb = Client ()
99
31
super (BitbucketService , self ).__init__ (* args , ** kwarg )
100
32
101
33
def connect (self ):
102
34
if not self ._privatekey :
103
35
raise ConnectionError ('Could not connect to BitBucket. Please configure .gitconfig with your bitbucket credentials.' )
104
36
if not ':' in self ._privatekey :
105
37
raise ConnectionError ('Could not connect to BitBucket. Please setup your private key with login:password' )
106
- self .bb .username , self .bb .password = self ._privatekey .split (':' )
107
- self .username = self .bb .username
108
- result , _ = self .bb .get_user ()
109
- if not result :
110
- raise ConnectionError ('Could not connect to BitBucket. Not authorized, wrong credentials.' )
38
+ self .
bb .
config = BasicAuthenticator (
* self .
_privatekey .
split (
':' )
+ [
'[email protected] ' ])
39
+ self .bb .session = self .bb .config .session
40
+ try :
41
+ User .find_current_user (client = self .bb )
42
+ except HTTPError as err :
43
+ raise ConnectionError ('Could not connect to BitBucket. Not authorized, wrong credentials.' ) from err
111
44
112
45
def create (self , user , repo , add = False ):
113
- success , result = self .bb .repository .create (repo , scm = 'git' , public = True )
114
- if not success and result ['code' ] == 400 :
115
- raise ResourceExistsError ('Project {} already exists on this account.' .format (repo ))
116
- elif not success :
117
- raise ResourceError ("Couldn't complete creation: {message} (error #{code}: {reason})" .format (** result ))
118
- if add :
119
- self .add (user = user , repo = repo , tracking = self .name )
46
+ try :
47
+ repo = Repository .create (
48
+ repo ,
49
+ fork_policy = RepositoryForkPolicy .ALLOW_FORKS ,
50
+ is_private = False ,
51
+ client = self .bb
52
+ )
53
+ if add :
54
+ self .add (user = user , repo = repo , tracking = self .name )
55
+ except HTTPError as err :
56
+ if err .status_code == 400 :
57
+ raise ResourceExistsError ('Project {} already exists on this account.' .format (repo )) from err
58
+ raise ResourceError ("Couldn't complete creation: {}" .format (err )) from err
120
59
121
60
def fork (self , user , repo ):
122
- success , result = self .bb .fork (user , repo )
123
- if not success :
124
- raise ResourceError ("Couldn't complete fork: {message} (error #{code}: {reason})" .format (** result ))
61
+ raise NotImplementedError ('No support yet by the underlying library.' )
62
+ try :
63
+ Repository .find_repository_by_name_and_owner (repo , owner = user , client = self .bb ).fork ()
64
+ except HTTPError as err :
65
+ raise ResourceError ("Couldn't complete creation: {}" .format (err )) from err
125
66
return '/' .join ([result ['owner' ], result ['slug' ]])
126
67
127
68
def delete (self , repo , user = None ):
128
69
if not user :
129
70
user = self .user
130
- success , result = self .bb .delete (user , repo )
131
- if not success and result ['code' ] == 404 :
132
- raise ResourceNotFoundError ("Cannot delete: repository {}/{} does not exists." .format (user , repo ))
133
- elif not success :
134
- raise ResourceError ("Couldn't complete deletion: {message} (error #{code}: {reason})" .format (** result ))
71
+ try :
72
+ Repository .find_repository_by_name_and_owner (repo , owner = user , client = self .bb ).delete ()
73
+ except HTTPError as err :
74
+ if err .status_code == 404 :
75
+ raise ResourceNotFoundError ("Cannot delete: repository {}/{} does not exists." .format (user , repo )) from err
76
+ raise ResourceError ("Couldn't complete creation: {}" .format (err )) from err
135
77
136
78
def get_repository (self , user , repo ):
137
- if user != self .user :
138
- result , repo_list = self .bb .repository .public (user )
139
- else :
140
- result , repo_list = self .bb .repository .all ()
141
- if not result :
142
- raise ResourceError ("Couldn't list repositories: {message} (error #{code}: {reason})" .format (** repo_list ))
143
- for r in repo_list :
144
- if r ['name' ] == repo :
145
- return r
146
- #raise ResourceNotFoundError('Cannot retrieve repository: {}/{} does not exists.'.format(user, repo))
79
+ try :
80
+ return Repository .find_repository_by_name_and_owner (repo , owner = user , client = self .bb )
81
+ except HTTPError as err :
82
+ raise ResourceNotFoundError ('Cannot retrieve repository: {}/{} does not exists.' .format (user , repo ))
147
83
148
84
@classmethod
149
85
def get_auth_token (cls , login , password , prompt = None ):
@@ -152,9 +88,9 @@ def get_auth_token(cls, login, password, prompt=None):
152
88
153
89
@property
154
90
def user (self ):
155
- ret , user = self . bb . get_user ()
156
- if ret :
157
- return user [ 'username' ]
158
- raise ResourceError ("Could not retrieve username : {message} (error #{code}: {reason} " .format (** result ))
91
+ try :
92
+ return User . find_current_user ( client = self . bb ). username
93
+ except HTTPError as err :
94
+ raise ResourceError ("Couldn't complete creation : {} " .format (err )) from err
159
95
160
96
0 commit comments