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>
This commit is contained in:
a1012112796 2021-07-05 23:29:08 +08:00 committed by GitHub
parent 64122fe105
commit 5bb97a12d7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 296 additions and 0 deletions

View file

@ -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).

View file

@ -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

View file

@ -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