7
7
from ...exceptions import ArgumentError , ResourceError , ResourceExistsError , ResourceNotFoundError
8
8
9
9
import gitlab
10
- from gitlab .exceptions import GitlabCreateError , GitlabGetError
10
+ from gitlab .exceptions import GitlabListError , GitlabCreateError , GitlabGetError
11
11
12
+ from git .exc import GitCommandError
13
+
14
+ import os
12
15
import json , time
13
16
14
17
@register_target ('lab' , 'gitlab' )
@@ -140,53 +143,56 @@ def get_auth_token(cls, login, password, prompt=None):
140
143
return gl .user .private_token
141
144
142
145
def _deconstruct_snippet_uri (self , uri ):
143
- path = uri .split ('https://{}/' .format (self .fqdn ))[- 1 ]
144
- path = path .split ('/' )
145
- if 3 == len (path ):
146
+ path = uri .split ('https://{}/' .format (self .fqdn ))[- 1 ].split ('/' )
147
+ if 4 == len (path ):
146
148
user , project_name , _ , snippet_id = path
147
- elif 4 == len (path ):
148
- user , _ , snippet_id = path
149
+ elif 2 == len (path ):
150
+ _ , snippet_id = path
151
+ project_name = None
152
+ user = None
153
+ elif 1 == len (path ):
154
+ snippet_id = path [0 ]
149
155
project_name = None
156
+ user = None
150
157
else :
151
158
raise ResourceNotFoundError ('URL is not of a snippet' )
152
159
return (user , project_name , snippet_id )
153
160
154
161
def gist_list (self , project = None ):
155
162
if not project :
156
- raise NotImplementedError ( 'Feature API implementation scheduled for gitlab 8.15' )
157
- for project in self .gl .snippets .list ():
158
- yield ('https://{}/{}/snippets/{}' . format (
159
- self . fqdn ,
160
- snippet . author . username ,
161
- snippet . id
162
- ), snippet . title )
163
+ try :
164
+ for snippet in self .gl .snippets .list ():
165
+ yield (snippet . web_url , snippet . title )
166
+ except GitlabListError as err :
167
+ if err . response_code == 404 :
168
+ raise ResourceNotFoundError ( 'Feature not available, please upgrade your gitlab instance.' ) from err
169
+ raise ResourceError ( 'Cannot list snippet' ) from err
163
170
else :
164
- project = self .gl .projects .list (search = project )
165
- if len (project ):
166
- project = project [0 ]
167
- for snippet in project .snippets .list (per_page = 100 ):
168
- yield ('https://{}/{}/{}/snippets/{}' .format (
169
- self .fqdn ,
170
- snippet .author .username ,
171
- project .name ,
172
- snippet .id
173
- ), 0 , snippet .title )
171
+ if '/' not in project :
172
+ project = '/' .join ([self .username , project ])
173
+ try :
174
+ project = self .gl .projects .get (project )
175
+ for snippet in project .snippets .list ():
176
+ yield (snippet .web_url , 0 , snippet .title )
177
+ except GitlabGetError as err :
178
+ raise ResourceNotFoundError ('Could not retrieve project "{}".' .format (project )) from err
174
179
175
180
def gist_fetch (self , snippet , fname = None ):
176
181
if fname :
177
182
raise ArgumentError ('Snippets contain only single file in gitlab.' )
178
183
try :
179
- _ , project_name , snippet_id = self ._deconstruct_snippet_uri (snippet )
180
- if project_name :
181
- project = self .gl .projects .list (search = project_name )[0 ]
182
- snippet = self .gl .project_snippets .get (project_id = project .id , id = snippet_id )
183
- else :
184
- raise NotImplementedError ('Feature API implementation scheduled for gitlab 8.15' )
185
- snippet = self .gl .snippets .get (id = snippet_id )
184
+ * _ , snippet_id = self ._deconstruct_snippet_uri (snippet )
185
+ snippet = self .gl .snippets .get (id = snippet_id )
186
+ except GitlabGetError as err :
187
+ if err .response_code == 404 :
188
+ if "The page you're looking for could not be found." in err .response_body .decode ('utf-8' ):
189
+ raise ResourceNotFoundError ('Feature not available, please upgrade your gitlab instance.' ) from err
190
+ raise ResourceNotFoundError ('Cannot fetch snippet' ) from err
191
+ raise ResourceError ('Cannot fetch snippet' ) from err
186
192
except Exception as err :
187
193
raise ResourceNotFoundError ('Could not find snippet' ) from err
188
194
189
- return snippet .Content ().decode ('utf-8' )
195
+ return snippet .raw ().decode ('utf-8' )
190
196
191
197
def gist_clone (self , gist ):
192
198
raise ArgumentError ('Snippets cannot be cloned in gitlab.' )
@@ -204,52 +210,71 @@ def load_file(fname, path='.'):
204
210
'visibility_level' : 0 if secret else 20
205
211
}
206
212
207
- if len (gist_pathes ) == 2 :
208
- gist_proj = gist_pathes [0 ]
209
- gist_path = gist_pathes [1 ]
210
- data .update ({
211
- 'id' : gist_proj ,
212
- 'code' : load_file (gist_path ),
213
- 'file_name' : os .path .basename (gist_path ),
214
- }
215
- )
216
- gist = self .gl .project_snippets .create (data )
217
-
218
- elif len (gist_pathes ) == 1 :
219
- raise NotImplementedError ('Feature API implementation scheduled for gitlab 8.15' )
220
- gist_path = gist_pathes [0 ]
221
- data .update ({
222
- 'content' : load_file (gist_path ),
223
- 'file_name' : os .path .basename (gist_path ),
224
- }
225
- )
226
- gist = self .gl .snippets .create (data )
227
-
228
- return gist .html_url
229
-
230
- def gist_delete (self , gist_id ):
231
213
try :
232
- _ , project_name , snippet_id = self ._deconstruct_snippet_uri (snippet )
233
- if project_name :
234
- project = self .gl .projects .list (search = project_name )[0 ]
235
- snippet = self .gl .project_snippets .get (project_id = project .id , id = snippet_id )
214
+
215
+ if len (gist_pathes ) == 2 :
216
+ project = gist_pathes [0 ]
217
+ if '/' in project :
218
+ * namespace , project = project .split ('/' )
219
+ namespace = '/' .join (namespace )
220
+ else :
221
+ namespace = self .username
222
+ gist_path = gist_pathes [1 ]
223
+ data .update ({
224
+ 'project_id' : '/' .join ([namespace , project ]),
225
+ 'code' : load_file (gist_path ),
226
+ 'file_name' : os .path .basename (gist_path ),
227
+ }
228
+ )
229
+ gist = self .gl .project_snippets .create (data )
230
+
231
+ elif len (gist_pathes ) == 1 :
232
+ gist_path = gist_pathes [0 ]
233
+ data .update ({
234
+ 'content' : load_file (gist_path ),
235
+ 'file_name' : os .path .basename (gist_path ),
236
+ }
237
+ )
238
+ gist = self .gl .snippets .create (data )
239
+
240
+ return gist .web_url
241
+ except GitlabCreateError as err :
242
+ if err .response_code == 422 :
243
+ raise ResourceNotFoundError ('Feature not available, please upgrade your gitlab instance.' ) from err
244
+ raise ResourceError ('Cannot create snippet' ) from err
245
+
246
+ def gist_delete (self , snippet ):
247
+ try :
248
+ _ , project , snippet_id = self ._deconstruct_snippet_uri (snippet )
249
+ if project :
250
+ if '/' in project :
251
+ * namespace , project = project .split ('/' )
252
+ namespace = '/' .join (namespace )
253
+ else :
254
+ namespace = self .username
255
+ snippet = self .gl .projects .get (
256
+ '/' .join ([namespace , project ])
257
+ ).snippets .get (id = snippet_id )
236
258
else :
237
- raise NotImplementedError ('Pending feature' )
238
259
snippet = self .gl .snippets .get (id = snippet_id )
260
+ except GitlabCreateError as err :
261
+ if err .response_code == 422 :
262
+ raise ResourceNotFoundError ('Cannot delete snippet, please upgrade your gitlab instance.' ) from err
263
+ raise ResourceError ('Cannot delete snippet' ) from err
239
264
except Exception as err :
240
265
raise ResourceNotFoundError ('Could not find snippet' ) from err
241
266
242
267
return snippet .delete ()
243
268
244
269
def request_create (self , user , repo , local_branch , remote_branch , title , description = None ):
245
- repository = self .gl .projects .list (search = repo )[0 ]
246
- if not repository :
247
- raise ResourceNotFoundError ('Could not find repository `{}/{}`!' .format (user , repo ))
248
- if not local_branch :
249
- remote_branch = self .repository .active_branch .name or self .repository .active_branch .name
250
- if not remote_branch :
251
- local_branch = repository .master_branch or 'master'
252
270
try :
271
+ repository = self .gl .projects .get ('/' .join ([user , repo ]))
272
+ if not repository :
273
+ raise ResourceNotFoundError ('Could not find repository `{}/{}`!' .format (user , repo ))
274
+ if not local_branch :
275
+ remote_branch = self .repository .active_branch .name or self .repository .active_branch .name
276
+ if not remote_branch :
277
+ local_branch = repository .master_branch or 'master'
253
278
request = self .gl .project_mergerequests .create (
254
279
project_id = repository .id ,
255
280
data = {
@@ -259,6 +284,8 @@ def request_create(self, user, repo, local_branch, remote_branch, title, descrip
259
284
'description' :description
260
285
}
261
286
)
287
+ except GitlabGetError as err :
288
+ raise ResourceNotFoundError (err ) from err
262
289
except Exception as err :
263
290
raise ResourceError ("Unhandled error: {}" .format (err )) from err
264
291
@@ -267,7 +294,7 @@ def request_create(self, user, repo, local_branch, remote_branch, title, descrip
267
294
'ref' : request .iid }
268
295
269
296
def request_list (self , user , repo ):
270
- project = self .gl .projects .list ( search = repo )[ 0 ]
297
+ project = self .gl .projects .get ( '/' . join ([ user , repo ]))
271
298
for mr in self .gl .project_mergerequests .list (project_id = project .id ):
272
299
yield ( str (mr .iid ),
273
300
mr .title ,
@@ -285,10 +312,10 @@ def request_fetch(self, user, repo, request, pull=False):
285
312
try :
286
313
for remote in self .repository .remotes :
287
314
if remote .name == self .name :
288
- local_branch_name = 'request /{}' .format (request )
315
+ local_branch_name = 'requests/gitlab /{}' .format (request )
289
316
self .fetch (
290
317
remote ,
291
- 'merge-requests /{}/head' .format (request ),
318
+ 'merge_requests /{}/head' .format (request ),
292
319
local_branch_name
293
320
)
294
321
return local_branch_name
0 commit comments