mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	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:
		@@ -495,6 +495,43 @@ func TestAPIRepoTransfer(t *testing.T) {
 | 
				
			|||||||
	_ = models.DeleteRepository(user, repo.OwnerID, repo.ID)
 | 
						_ = models.DeleteRepository(user, repo.OwnerID, repo.ID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestAPIGenerateRepo(t *testing.T) {
 | 
				
			||||||
 | 
						defer prepareTestEnv(t)()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						user := models.AssertExistsAndLoadBean(t, &models.User{ID: 1}).(*models.User)
 | 
				
			||||||
 | 
						session := loginUser(t, user.Name)
 | 
				
			||||||
 | 
						token := getTokenForLoggedInUser(t, session)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						templateRepo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 44}).(*models.Repository)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// user
 | 
				
			||||||
 | 
						repo := new(api.Repository)
 | 
				
			||||||
 | 
						req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/generate?token=%s", templateRepo.OwnerName, templateRepo.Name, token), &api.GenerateRepoOption{
 | 
				
			||||||
 | 
							Owner:       user.Name,
 | 
				
			||||||
 | 
							Name:        "new-repo",
 | 
				
			||||||
 | 
							Description: "test generate repo",
 | 
				
			||||||
 | 
							Private:     false,
 | 
				
			||||||
 | 
							GitContent:  true,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						resp := session.MakeRequest(t, req, http.StatusCreated)
 | 
				
			||||||
 | 
						DecodeJSON(t, resp, repo)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert.Equal(t, "new-repo", repo.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// org
 | 
				
			||||||
 | 
						req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/generate?token=%s", templateRepo.OwnerName, templateRepo.Name, token), &api.GenerateRepoOption{
 | 
				
			||||||
 | 
							Owner:       "user3",
 | 
				
			||||||
 | 
							Name:        "new-repo",
 | 
				
			||||||
 | 
							Description: "test generate repo",
 | 
				
			||||||
 | 
							Private:     false,
 | 
				
			||||||
 | 
							GitContent:  true,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						resp = session.MakeRequest(t, req, http.StatusCreated)
 | 
				
			||||||
 | 
						DecodeJSON(t, resp, repo)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert.Equal(t, "new-repo", repo.Name)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestAPIRepoGetReviewers(t *testing.T) {
 | 
					func TestAPIRepoGetReviewers(t *testing.T) {
 | 
				
			||||||
	defer prepareTestEnv(t)()
 | 
						defer prepareTestEnv(t)()
 | 
				
			||||||
	user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
 | 
						user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -180,6 +180,36 @@ type EditRepoOption struct {
 | 
				
			|||||||
	MirrorInterval *string `json:"mirror_interval,omitempty"`
 | 
						MirrorInterval *string `json:"mirror_interval,omitempty"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GenerateRepoOption options when creating repository using a template
 | 
				
			||||||
 | 
					// swagger:model
 | 
				
			||||||
 | 
					type GenerateRepoOption struct {
 | 
				
			||||||
 | 
						// The organization or person who will own the new repository
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// required: true
 | 
				
			||||||
 | 
						Owner string `json:"owner"`
 | 
				
			||||||
 | 
						// Name of the repository to create
 | 
				
			||||||
 | 
						//
 | 
				
			||||||
 | 
						// required: true
 | 
				
			||||||
 | 
						// unique: true
 | 
				
			||||||
 | 
						Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(100)"`
 | 
				
			||||||
 | 
						// Description of the repository to create
 | 
				
			||||||
 | 
						Description string `json:"description" binding:"MaxSize(255)"`
 | 
				
			||||||
 | 
						// Whether the repository is private
 | 
				
			||||||
 | 
						Private bool `json:"private"`
 | 
				
			||||||
 | 
						// include git content of default branch in template repo
 | 
				
			||||||
 | 
						GitContent bool `json:"git_content"`
 | 
				
			||||||
 | 
						// include topics in template repo
 | 
				
			||||||
 | 
						Topics bool `json:"topics"`
 | 
				
			||||||
 | 
						// include git hooks in template repo
 | 
				
			||||||
 | 
						GitHooks bool `json:"git_hooks"`
 | 
				
			||||||
 | 
						// include webhooks in template repo
 | 
				
			||||||
 | 
						Webhooks bool `json:"webhooks"`
 | 
				
			||||||
 | 
						// include avatar of the template repo
 | 
				
			||||||
 | 
						Avatar bool `json:"avatar"`
 | 
				
			||||||
 | 
						// include labels in template repo
 | 
				
			||||||
 | 
						Labels bool `json:"labels"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CreateBranchRepoOption options when creating a branch in a repository
 | 
					// CreateBranchRepoOption options when creating a branch in a repository
 | 
				
			||||||
// swagger:model
 | 
					// swagger:model
 | 
				
			||||||
type CreateBranchRepoOption struct {
 | 
					type CreateBranchRepoOption struct {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -722,6 +722,7 @@ func Routes() *web.Route {
 | 
				
			|||||||
				m.Combo("").Get(reqAnyRepoReader(), repo.Get).
 | 
									m.Combo("").Get(reqAnyRepoReader(), repo.Get).
 | 
				
			||||||
					Delete(reqToken(), reqOwner(), repo.Delete).
 | 
										Delete(reqToken(), reqOwner(), repo.Delete).
 | 
				
			||||||
					Patch(reqToken(), reqAdmin(), bind(api.EditRepoOption{}), repo.Edit)
 | 
										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.Post("/transfer", reqOwner(), bind(api.TransferRepoOption{}), repo.Transfer)
 | 
				
			||||||
				m.Combo("/notifications").
 | 
									m.Combo("/notifications").
 | 
				
			||||||
					Get(reqToken(), notify.ListRepoNotifications).
 | 
										Get(reqToken(), notify.ListRepoNotifications).
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -307,6 +307,115 @@ func Create(ctx *context.APIContext) {
 | 
				
			|||||||
	CreateUserRepo(ctx, ctx.User, *opt)
 | 
						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
 | 
					// CreateOrgRepoDeprecated create one repository of the organization
 | 
				
			||||||
func CreateOrgRepoDeprecated(ctx *context.APIContext) {
 | 
					func CreateOrgRepoDeprecated(ctx *context.APIContext) {
 | 
				
			||||||
	// swagger:operation POST /org/{org}/repos organization createOrgRepoDeprecated
 | 
						// swagger:operation POST /org/{org}/repos organization createOrgRepoDeprecated
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,6 +87,8 @@ type swaggerParameterBodies struct {
 | 
				
			|||||||
	TransferRepoOption api.TransferRepoOption
 | 
						TransferRepoOption api.TransferRepoOption
 | 
				
			||||||
	// in:body
 | 
						// in:body
 | 
				
			||||||
	CreateForkOption api.CreateForkOption
 | 
						CreateForkOption api.CreateForkOption
 | 
				
			||||||
 | 
						// in:body
 | 
				
			||||||
 | 
						GenerateRepoOption api.GenerateRepoOption
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// in:body
 | 
						// in:body
 | 
				
			||||||
	CreateStatusOption api.CreateStatusOption
 | 
						CreateStatusOption api.CreateStatusOption
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9777,6 +9777,61 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "/repos/{template_owner}/{template_repo}/generate": {
 | 
				
			||||||
 | 
					      "post": {
 | 
				
			||||||
 | 
					        "consumes": [
 | 
				
			||||||
 | 
					          "application/json"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "produces": [
 | 
				
			||||||
 | 
					          "application/json"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "tags": [
 | 
				
			||||||
 | 
					          "repository"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "summary": "Create a repository using a template",
 | 
				
			||||||
 | 
					        "operationId": "generateRepo",
 | 
				
			||||||
 | 
					        "parameters": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "type": "string",
 | 
				
			||||||
 | 
					            "description": "name of the template repository owner",
 | 
				
			||||||
 | 
					            "name": "template_owner",
 | 
				
			||||||
 | 
					            "in": "path",
 | 
				
			||||||
 | 
					            "required": true
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "type": "string",
 | 
				
			||||||
 | 
					            "description": "name of the template repository",
 | 
				
			||||||
 | 
					            "name": "template_repo",
 | 
				
			||||||
 | 
					            "in": "path",
 | 
				
			||||||
 | 
					            "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"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "/repositories/{id}": {
 | 
					    "/repositories/{id}": {
 | 
				
			||||||
      "get": {
 | 
					      "get": {
 | 
				
			||||||
        "produces": [
 | 
					        "produces": [
 | 
				
			||||||
@@ -14551,6 +14606,68 @@
 | 
				
			|||||||
      },
 | 
					      },
 | 
				
			||||||
      "x-go-package": "code.gitea.io/gitea/modules/structs"
 | 
					      "x-go-package": "code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "GenerateRepoOption": {
 | 
				
			||||||
 | 
					      "description": "GenerateRepoOption options when creating repository using a template",
 | 
				
			||||||
 | 
					      "type": "object",
 | 
				
			||||||
 | 
					      "required": [
 | 
				
			||||||
 | 
					        "owner",
 | 
				
			||||||
 | 
					        "name"
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      "properties": {
 | 
				
			||||||
 | 
					        "avatar": {
 | 
				
			||||||
 | 
					          "description": "include avatar of the template repo",
 | 
				
			||||||
 | 
					          "type": "boolean",
 | 
				
			||||||
 | 
					          "x-go-name": "Avatar"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "description": {
 | 
				
			||||||
 | 
					          "description": "Description of the repository to create",
 | 
				
			||||||
 | 
					          "type": "string",
 | 
				
			||||||
 | 
					          "x-go-name": "Description"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "git_content": {
 | 
				
			||||||
 | 
					          "description": "include git content of default branch in template repo",
 | 
				
			||||||
 | 
					          "type": "boolean",
 | 
				
			||||||
 | 
					          "x-go-name": "GitContent"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "git_hooks": {
 | 
				
			||||||
 | 
					          "description": "include git hooks in template repo",
 | 
				
			||||||
 | 
					          "type": "boolean",
 | 
				
			||||||
 | 
					          "x-go-name": "GitHooks"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "labels": {
 | 
				
			||||||
 | 
					          "description": "include labels in template repo",
 | 
				
			||||||
 | 
					          "type": "boolean",
 | 
				
			||||||
 | 
					          "x-go-name": "Labels"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "name": {
 | 
				
			||||||
 | 
					          "description": "Name of the repository to create",
 | 
				
			||||||
 | 
					          "type": "string",
 | 
				
			||||||
 | 
					          "uniqueItems": true,
 | 
				
			||||||
 | 
					          "x-go-name": "Name"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "owner": {
 | 
				
			||||||
 | 
					          "description": "The organization or person who will own the new repository",
 | 
				
			||||||
 | 
					          "type": "string",
 | 
				
			||||||
 | 
					          "x-go-name": "Owner"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "private": {
 | 
				
			||||||
 | 
					          "description": "Whether the repository is private",
 | 
				
			||||||
 | 
					          "type": "boolean",
 | 
				
			||||||
 | 
					          "x-go-name": "Private"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "topics": {
 | 
				
			||||||
 | 
					          "description": "include topics in template repo",
 | 
				
			||||||
 | 
					          "type": "boolean",
 | 
				
			||||||
 | 
					          "x-go-name": "Topics"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "webhooks": {
 | 
				
			||||||
 | 
					          "description": "include webhooks in template repo",
 | 
				
			||||||
 | 
					          "type": "boolean",
 | 
				
			||||||
 | 
					          "x-go-name": "Webhooks"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "x-go-package": "code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "GitBlobResponse": {
 | 
					    "GitBlobResponse": {
 | 
				
			||||||
      "description": "GitBlobResponse represents a git blob",
 | 
					      "description": "GitBlobResponse represents a git blob",
 | 
				
			||||||
      "type": "object",
 | 
					      "type": "object",
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user