@@ -307,6 +307,115 @@ func Create(ctx *context.APIContext) {
307307 CreateUserRepo (ctx , ctx .User , * opt )
308308}
309309
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+
310419// CreateOrgRepoDeprecated create one repository of the organization
311420func CreateOrgRepoDeprecated (ctx * context.APIContext ) {
312421 // swagger:operation POST /org/{org}/repos organization createOrgRepoDeprecated
0 commit comments