@@ -307,6 +307,115 @@ func Create(ctx *context.APIContext) {
307
307
CreateUserRepo (ctx , ctx .User , * opt )
308
308
}
309
309
310
+ // Generate Create a repository using a template
311
+ func Generate (ctx * context.APIContext ) {
312
+ // swagger:operation POST /repos/{template_owner}/{template_repo}/generate repository generateRepo
313
+ // ---
314
+ // summary: Create a repository using a template
315
+ // consumes:
316
+ // - application/json
317
+ // produces:
318
+ // - application/json
319
+ // parameters:
320
+ // - name: template_owner
321
+ // in: path
322
+ // description: name of the template repository owner
323
+ // type: string
324
+ // required: true
325
+ // - name: template_repo
326
+ // in: path
327
+ // description: name of the template repository
328
+ // type: string
329
+ // required: true
330
+ // - name: body
331
+ // in: body
332
+ // schema:
333
+ // "$ref": "#/definitions/GenerateRepoOption"
334
+ // responses:
335
+ // "201":
336
+ // "$ref": "#/responses/Repository"
337
+ // "403":
338
+ // "$ref": "#/responses/forbidden"
339
+ // "404":
340
+ // "$ref": "#/responses/notFound"
341
+ // "409":
342
+ // description: The repository with the same name already exists.
343
+ // "422":
344
+ // "$ref": "#/responses/validationError"
345
+ form := web .GetForm (ctx ).(* api.GenerateRepoOption )
346
+
347
+ if ! ctx .Repo .Repository .IsTemplate {
348
+ ctx .Error (http .StatusUnprocessableEntity , "" , "this is not a template repo" )
349
+ return
350
+ }
351
+
352
+ if ctx .User .IsOrganization () {
353
+ ctx .Error (http .StatusUnprocessableEntity , "" , "not allowed creating repository for organization" )
354
+ return
355
+ }
356
+
357
+ opts := models.GenerateRepoOptions {
358
+ Name : form .Name ,
359
+ Description : form .Description ,
360
+ Private : form .Private ,
361
+ GitContent : form .GitContent ,
362
+ Topics : form .Topics ,
363
+ GitHooks : form .GitHooks ,
364
+ Webhooks : form .Webhooks ,
365
+ Avatar : form .Avatar ,
366
+ IssueLabels : form .Labels ,
367
+ }
368
+
369
+ if ! opts .IsValid () {
370
+ ctx .Error (http .StatusUnprocessableEntity , "" , "must select at least one template item" )
371
+ return
372
+ }
373
+
374
+ ctxUser := ctx .User
375
+ var err error
376
+ if form .Owner != ctxUser .Name {
377
+ ctxUser , err = models .GetOrgByName (form .Owner )
378
+ if err != nil {
379
+ if models .IsErrOrgNotExist (err ) {
380
+ ctx .JSON (http .StatusNotFound , map [string ]interface {}{
381
+ "error" : "request owner `" + form .Name + "` is not exist" ,
382
+ })
383
+ return
384
+ }
385
+
386
+ ctx .Error (http .StatusInternalServerError , "GetOrgByName" , err )
387
+ return
388
+ }
389
+
390
+ if ! ctx .User .IsAdmin {
391
+ canCreate , err := ctxUser .CanCreateOrgRepo (ctx .User .ID )
392
+ if err != nil {
393
+ ctx .ServerError ("CanCreateOrgRepo" , err )
394
+ return
395
+ } else if ! canCreate {
396
+ ctx .Error (http .StatusForbidden , "" , "Given user is not allowed to create repository in organization." )
397
+ return
398
+ }
399
+ }
400
+ }
401
+
402
+ repo , err := repo_service .GenerateRepository (ctx .User , ctxUser , ctx .Repo .Repository , opts )
403
+ if err != nil {
404
+ if models .IsErrRepoAlreadyExist (err ) {
405
+ ctx .Error (http .StatusConflict , "" , "The repository with the same name already exists." )
406
+ } else if models .IsErrNameReserved (err ) ||
407
+ models .IsErrNamePatternNotAllowed (err ) {
408
+ ctx .Error (http .StatusUnprocessableEntity , "" , err )
409
+ } else {
410
+ ctx .Error (http .StatusInternalServerError , "CreateRepository" , err )
411
+ }
412
+ return
413
+ }
414
+ log .Trace ("Repository generated [%d]: %s/%s" , repo .ID , ctxUser .Name , repo .Name )
415
+
416
+ ctx .JSON (http .StatusCreated , convert .ToRepo (repo , models .AccessModeOwner ))
417
+ }
418
+
310
419
// CreateOrgRepoDeprecated create one repository of the organization
311
420
func CreateOrgRepoDeprecated (ctx * context.APIContext ) {
312
421
// swagger:operation POST /org/{org}/repos organization createOrgRepoDeprecated
0 commit comments