diff options
author | a1012112796 <1012112796@qq.com> | 2021-07-05 23:29:08 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-05 17:29:08 +0200 |
commit | 5bb97a12d79309e799e9826badf3527f03815dd2 (patch) | |
tree | 35e6a708ca49a01684ea97512055c0611552e7f4 /routers | |
parent | 64122fe105686502d4d5606425875a6b16fa6203 (diff) | |
download | gitea-5bb97a12d79309e799e9826badf3527f03815dd2.tar.gz gitea-5bb97a12d79309e799e9826badf3527f03815dd2.zip |
Creating a repo from a template repo via API (#15958)
* Creating a repo from a template repo via API
fix #15934
ref:
https://docs.github.com/en/rest/reference/repos#create-a-repository-using-a-template
Signed-off-by: a1012112796 <1012112796@qq.com>
Diffstat (limited to 'routers')
-rw-r--r-- | routers/api/v1/api.go | 1 | ||||
-rw-r--r-- | routers/api/v1/repo/repo.go | 109 | ||||
-rw-r--r-- | routers/api/v1/swagger/options.go | 2 |
3 files changed, 112 insertions, 0 deletions
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index b6913ea1bc..b4f14bf2d1 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -722,6 +722,7 @@ func Routes() *web.Route { m.Combo("").Get(reqAnyRepoReader(), repo.Get). Delete(reqToken(), reqOwner(), repo.Delete). Patch(reqToken(), reqAdmin(), bind(api.EditRepoOption{}), repo.Edit) + m.Post("/generate", reqToken(), reqRepoReader(models.UnitTypeCode), bind(api.GenerateRepoOption{}), repo.Generate) m.Post("/transfer", reqOwner(), bind(api.TransferRepoOption{}), repo.Transfer) m.Combo("/notifications"). Get(reqToken(), notify.ListRepoNotifications). diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 35d3490510..5d397191a6 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -307,6 +307,115 @@ func Create(ctx *context.APIContext) { CreateUserRepo(ctx, ctx.User, *opt) } +// Generate Create a repository using a template +func Generate(ctx *context.APIContext) { + // swagger:operation POST /repos/{template_owner}/{template_repo}/generate repository generateRepo + // --- + // summary: Create a repository using a template + // consumes: + // - application/json + // produces: + // - application/json + // parameters: + // - name: template_owner + // in: path + // description: name of the template repository owner + // type: string + // required: true + // - name: template_repo + // in: path + // description: name of the template repository + // type: string + // required: true + // - name: body + // in: body + // schema: + // "$ref": "#/definitions/GenerateRepoOption" + // responses: + // "201": + // "$ref": "#/responses/Repository" + // "403": + // "$ref": "#/responses/forbidden" + // "404": + // "$ref": "#/responses/notFound" + // "409": + // description: The repository with the same name already exists. + // "422": + // "$ref": "#/responses/validationError" + form := web.GetForm(ctx).(*api.GenerateRepoOption) + + if !ctx.Repo.Repository.IsTemplate { + ctx.Error(http.StatusUnprocessableEntity, "", "this is not a template repo") + return + } + + if ctx.User.IsOrganization() { + ctx.Error(http.StatusUnprocessableEntity, "", "not allowed creating repository for organization") + return + } + + opts := models.GenerateRepoOptions{ + Name: form.Name, + Description: form.Description, + Private: form.Private, + GitContent: form.GitContent, + Topics: form.Topics, + GitHooks: form.GitHooks, + Webhooks: form.Webhooks, + Avatar: form.Avatar, + IssueLabels: form.Labels, + } + + if !opts.IsValid() { + ctx.Error(http.StatusUnprocessableEntity, "", "must select at least one template item") + return + } + + ctxUser := ctx.User + var err error + if form.Owner != ctxUser.Name { + ctxUser, err = models.GetOrgByName(form.Owner) + if err != nil { + if models.IsErrOrgNotExist(err) { + ctx.JSON(http.StatusNotFound, map[string]interface{}{ + "error": "request owner `" + form.Name + "` is not exist", + }) + return + } + + ctx.Error(http.StatusInternalServerError, "GetOrgByName", err) + return + } + + if !ctx.User.IsAdmin { + canCreate, err := ctxUser.CanCreateOrgRepo(ctx.User.ID) + if err != nil { + ctx.ServerError("CanCreateOrgRepo", err) + return + } else if !canCreate { + ctx.Error(http.StatusForbidden, "", "Given user is not allowed to create repository in organization.") + return + } + } + } + + repo, err := repo_service.GenerateRepository(ctx.User, ctxUser, ctx.Repo.Repository, opts) + if err != nil { + if models.IsErrRepoAlreadyExist(err) { + ctx.Error(http.StatusConflict, "", "The repository with the same name already exists.") + } else if models.IsErrNameReserved(err) || + models.IsErrNamePatternNotAllowed(err) { + ctx.Error(http.StatusUnprocessableEntity, "", err) + } else { + ctx.Error(http.StatusInternalServerError, "CreateRepository", err) + } + return + } + log.Trace("Repository generated [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name) + + ctx.JSON(http.StatusCreated, convert.ToRepo(repo, models.AccessModeOwner)) +} + // CreateOrgRepoDeprecated create one repository of the organization func CreateOrgRepoDeprecated(ctx *context.APIContext) { // swagger:operation POST /org/{org}/repos organization createOrgRepoDeprecated diff --git a/routers/api/v1/swagger/options.go b/routers/api/v1/swagger/options.go index b5f34e86a3..0ae96a9203 100644 --- a/routers/api/v1/swagger/options.go +++ b/routers/api/v1/swagger/options.go @@ -87,6 +87,8 @@ type swaggerParameterBodies struct { TransferRepoOption api.TransferRepoOption // in:body CreateForkOption api.CreateForkOption + // in:body + GenerateRepoOption api.GenerateRepoOption // in:body CreateStatusOption api.CreateStatusOption |