_ = 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) {
defer prepareTestEnv(t)()
user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
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
// swagger:model
type CreateBranchRepoOption struct {
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).
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
TransferRepoOption api.TransferRepoOption
// in:body
CreateForkOption api.CreateForkOption
+ // in:body
+ GenerateRepoOption api.GenerateRepoOption
// in:body
CreateStatusOption api.CreateStatusOption
}
}
},
+ "/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}": {
"get": {
"produces": [
},
"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": {
"description": "GitBlobResponse represents a git blob",
"type": "object",