* Add API for Repo Advanced Settings of wiki and issue tracker Signed-off-by: David Svantesson <davidsvantesson@gmail.com> * Add some integration tests for tracker and wiki settings through API * Should return StatusUnprocessableEntity in case of invalid API values. * Add tests for invalid URLs for external tracker and wiki. * Do not set inital values if they are default of type * Make issue tracker and wiki units separate structures in Repository API structure. Signed-off-by: David Svantesson <davidsvantesson@gmail.com> * Fix comment of structures Signed-off-by: David Svantesson <davidsvantesson@gmail.com> * Rewrite API to use struct for setting tracker and wiki settings. * LetOnlyContributorsTrackTime -> AllowOnlyContributorsToTrackTimetags/v1.21.12.1
| @@ -23,12 +23,35 @@ func getRepoEditOptionFromRepo(repo *models.Repository) *api.EditRepoOption { | |||||
| website := repo.Website | website := repo.Website | ||||
| private := repo.IsPrivate | private := repo.IsPrivate | ||||
| hasIssues := false | hasIssues := false | ||||
| if _, err := repo.GetUnit(models.UnitTypeIssues); err == nil { | |||||
| var internalTracker *api.InternalTracker | |||||
| var externalTracker *api.ExternalTracker | |||||
| if unit, err := repo.GetUnit(models.UnitTypeIssues); err == nil { | |||||
| config := unit.IssuesConfig() | |||||
| hasIssues = true | hasIssues = true | ||||
| internalTracker = &api.InternalTracker{ | |||||
| EnableTimeTracker: config.EnableTimetracker, | |||||
| AllowOnlyContributorsToTrackTime: config.AllowOnlyContributorsToTrackTime, | |||||
| EnableIssueDependencies: config.EnableDependencies, | |||||
| } | |||||
| } else if unit, err := repo.GetUnit(models.UnitTypeExternalTracker); err == nil { | |||||
| config := unit.ExternalTrackerConfig() | |||||
| hasIssues = true | |||||
| externalTracker = &api.ExternalTracker{ | |||||
| ExternalTrackerURL: config.ExternalTrackerURL, | |||||
| ExternalTrackerFormat: config.ExternalTrackerFormat, | |||||
| ExternalTrackerStyle: config.ExternalTrackerStyle, | |||||
| } | |||||
| } | } | ||||
| hasWiki := false | hasWiki := false | ||||
| var externalWiki *api.ExternalWiki | |||||
| if _, err := repo.GetUnit(models.UnitTypeWiki); err == nil { | if _, err := repo.GetUnit(models.UnitTypeWiki); err == nil { | ||||
| hasWiki = true | hasWiki = true | ||||
| } else if unit, err := repo.GetUnit(models.UnitTypeExternalWiki); err == nil { | |||||
| hasWiki = true | |||||
| config := unit.ExternalWikiConfig() | |||||
| externalWiki = &api.ExternalWiki{ | |||||
| ExternalWikiURL: config.ExternalWikiURL, | |||||
| } | |||||
| } | } | ||||
| defaultBranch := repo.DefaultBranch | defaultBranch := repo.DefaultBranch | ||||
| hasPullRequests := false | hasPullRequests := false | ||||
| @@ -53,7 +76,10 @@ func getRepoEditOptionFromRepo(repo *models.Repository) *api.EditRepoOption { | |||||
| Website: &website, | Website: &website, | ||||
| Private: &private, | Private: &private, | ||||
| HasIssues: &hasIssues, | HasIssues: &hasIssues, | ||||
| ExternalTracker: externalTracker, | |||||
| InternalTracker: internalTracker, | |||||
| HasWiki: &hasWiki, | HasWiki: &hasWiki, | ||||
| ExternalWiki: externalWiki, | |||||
| DefaultBranch: &defaultBranch, | DefaultBranch: &defaultBranch, | ||||
| HasPullRequests: &hasPullRequests, | HasPullRequests: &hasPullRequests, | ||||
| IgnoreWhitespaceConflicts: &ignoreWhitespaceConflicts, | IgnoreWhitespaceConflicts: &ignoreWhitespaceConflicts, | ||||
| @@ -143,6 +169,84 @@ func TestAPIRepoEdit(t *testing.T) { | |||||
| assert.Equal(t, *repoEditOption.Archived, *repo1editedOption.Archived) | assert.Equal(t, *repoEditOption.Archived, *repo1editedOption.Archived) | ||||
| assert.Equal(t, *repoEditOption.Private, *repo1editedOption.Private) | assert.Equal(t, *repoEditOption.Private, *repo1editedOption.Private) | ||||
| assert.Equal(t, *repoEditOption.HasWiki, *repo1editedOption.HasWiki) | assert.Equal(t, *repoEditOption.HasWiki, *repo1editedOption.HasWiki) | ||||
| //Test editing repo1 to use internal issue and wiki (default) | |||||
| *repoEditOption.HasIssues = true | |||||
| repoEditOption.ExternalTracker = nil | |||||
| repoEditOption.InternalTracker = &api.InternalTracker{ | |||||
| EnableTimeTracker: false, | |||||
| AllowOnlyContributorsToTrackTime: false, | |||||
| EnableIssueDependencies: false, | |||||
| } | |||||
| *repoEditOption.HasWiki = true | |||||
| repoEditOption.ExternalWiki = nil | |||||
| url = fmt.Sprintf("/api/v1/repos/%s/%s?token=%s", user2.Name, *repoEditOption.Name, token2) | |||||
| req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption) | |||||
| resp = session.MakeRequest(t, req, http.StatusOK) | |||||
| DecodeJSON(t, resp, &repo) | |||||
| assert.NotNil(t, repo) | |||||
| // check repo1 was written to database | |||||
| repo1edited = models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) | |||||
| repo1editedOption = getRepoEditOptionFromRepo(repo1edited) | |||||
| assert.Equal(t, *repo1editedOption.HasIssues, true) | |||||
| assert.Nil(t, repo1editedOption.ExternalTracker) | |||||
| assert.Equal(t, *repo1editedOption.InternalTracker, *repoEditOption.InternalTracker) | |||||
| assert.Equal(t, *repo1editedOption.HasWiki, true) | |||||
| assert.Nil(t, repo1editedOption.ExternalWiki) | |||||
| //Test editing repo1 to use external issue and wiki | |||||
| repoEditOption.ExternalTracker = &api.ExternalTracker{ | |||||
| ExternalTrackerURL: "http://www.somewebsite.com", | |||||
| ExternalTrackerFormat: "http://www.somewebsite.com/{user}/{repo}?issue={index}", | |||||
| ExternalTrackerStyle: "alphanumeric", | |||||
| } | |||||
| repoEditOption.ExternalWiki = &api.ExternalWiki{ | |||||
| ExternalWikiURL: "http://www.somewebsite.com", | |||||
| } | |||||
| req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption) | |||||
| resp = session.MakeRequest(t, req, http.StatusOK) | |||||
| DecodeJSON(t, resp, &repo) | |||||
| assert.NotNil(t, repo) | |||||
| // check repo1 was written to database | |||||
| repo1edited = models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) | |||||
| repo1editedOption = getRepoEditOptionFromRepo(repo1edited) | |||||
| assert.Equal(t, *repo1editedOption.HasIssues, true) | |||||
| assert.Equal(t, *repo1editedOption.ExternalTracker, *repoEditOption.ExternalTracker) | |||||
| assert.Equal(t, *repo1editedOption.HasWiki, true) | |||||
| assert.Equal(t, *repo1editedOption.ExternalWiki, *repoEditOption.ExternalWiki) | |||||
| // Do some tests with invalid URL for external tracker and wiki | |||||
| repoEditOption.ExternalTracker.ExternalTrackerURL = "htp://www.somewebsite.com" | |||||
| req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption) | |||||
| resp = session.MakeRequest(t, req, http.StatusUnprocessableEntity) | |||||
| repoEditOption.ExternalTracker.ExternalTrackerURL = "http://www.somewebsite.com" | |||||
| repoEditOption.ExternalTracker.ExternalTrackerFormat = "http://www.somewebsite.com/{user/{repo}?issue={index}" | |||||
| req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption) | |||||
| resp = session.MakeRequest(t, req, http.StatusUnprocessableEntity) | |||||
| repoEditOption.ExternalTracker.ExternalTrackerFormat = "http://www.somewebsite.com/{user}/{repo}?issue={index}" | |||||
| repoEditOption.ExternalWiki.ExternalWikiURL = "htp://www.somewebsite.com" | |||||
| req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption) | |||||
| resp = session.MakeRequest(t, req, http.StatusUnprocessableEntity) | |||||
| //Test small repo change through API with issue and wiki option not set; They shall not be touched. | |||||
| *repoEditOption.Description = "small change" | |||||
| repoEditOption.HasIssues = nil | |||||
| repoEditOption.ExternalTracker = nil | |||||
| repoEditOption.HasWiki = nil | |||||
| repoEditOption.ExternalWiki = nil | |||||
| req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption) | |||||
| resp = session.MakeRequest(t, req, http.StatusOK) | |||||
| DecodeJSON(t, resp, &repo) | |||||
| assert.NotNil(t, repo) | |||||
| // check repo1 was written to database | |||||
| repo1edited = models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) | |||||
| repo1editedOption = getRepoEditOptionFromRepo(repo1edited) | |||||
| assert.Equal(t, *repo1editedOption.Description, *repoEditOption.Description) | |||||
| assert.Equal(t, *repo1editedOption.HasIssues, true) | |||||
| assert.NotNil(t, *repo1editedOption.ExternalTracker) | |||||
| assert.Equal(t, *repo1editedOption.HasWiki, true) | |||||
| assert.NotNil(t, *repo1editedOption.ExternalWiki) | |||||
| // reset repo in db | // reset repo in db | ||||
| url = fmt.Sprintf("/api/v1/repos/%s/%s?token=%s", user2.Name, *repoEditOption.Name, token2) | url = fmt.Sprintf("/api/v1/repos/%s/%s?token=%s", user2.Name, *repoEditOption.Name, token2) | ||||
| req = NewRequestWithJSON(t, "PATCH", url, &origRepoEditOption) | req = NewRequestWithJSON(t, "PATCH", url, &origRepoEditOption) | ||||
| @@ -275,12 +275,35 @@ func (repo *Repository) innerAPIFormat(e Engine, mode AccessMode, isParent bool) | |||||
| } | } | ||||
| } | } | ||||
| hasIssues := false | hasIssues := false | ||||
| if _, err := repo.getUnit(e, UnitTypeIssues); err == nil { | |||||
| var externalTracker *api.ExternalTracker | |||||
| var internalTracker *api.InternalTracker | |||||
| if unit, err := repo.getUnit(e, UnitTypeIssues); err == nil { | |||||
| config := unit.IssuesConfig() | |||||
| hasIssues = true | hasIssues = true | ||||
| internalTracker = &api.InternalTracker{ | |||||
| EnableTimeTracker: config.EnableTimetracker, | |||||
| AllowOnlyContributorsToTrackTime: config.AllowOnlyContributorsToTrackTime, | |||||
| EnableIssueDependencies: config.EnableDependencies, | |||||
| } | |||||
| } else if unit, err := repo.getUnit(e, UnitTypeExternalTracker); err == nil { | |||||
| config := unit.ExternalTrackerConfig() | |||||
| hasIssues = true | |||||
| externalTracker = &api.ExternalTracker{ | |||||
| ExternalTrackerURL: config.ExternalTrackerURL, | |||||
| ExternalTrackerFormat: config.ExternalTrackerFormat, | |||||
| ExternalTrackerStyle: config.ExternalTrackerStyle, | |||||
| } | |||||
| } | } | ||||
| hasWiki := false | hasWiki := false | ||||
| var externalWiki *api.ExternalWiki | |||||
| if _, err := repo.getUnit(e, UnitTypeWiki); err == nil { | if _, err := repo.getUnit(e, UnitTypeWiki); err == nil { | ||||
| hasWiki = true | hasWiki = true | ||||
| } else if unit, err := repo.getUnit(e, UnitTypeExternalWiki); err == nil { | |||||
| hasWiki = true | |||||
| config := unit.ExternalWikiConfig() | |||||
| externalWiki = &api.ExternalWiki{ | |||||
| ExternalWikiURL: config.ExternalWikiURL, | |||||
| } | |||||
| } | } | ||||
| hasPullRequests := false | hasPullRequests := false | ||||
| ignoreWhitespaceConflicts := false | ignoreWhitespaceConflicts := false | ||||
| @@ -324,7 +347,10 @@ func (repo *Repository) innerAPIFormat(e Engine, mode AccessMode, isParent bool) | |||||
| Updated: repo.UpdatedUnix.AsTime(), | Updated: repo.UpdatedUnix.AsTime(), | ||||
| Permissions: permission, | Permissions: permission, | ||||
| HasIssues: hasIssues, | HasIssues: hasIssues, | ||||
| ExternalTracker: externalTracker, | |||||
| InternalTracker: internalTracker, | |||||
| HasWiki: hasWiki, | HasWiki: hasWiki, | ||||
| ExternalWiki: externalWiki, | |||||
| HasPullRequests: hasPullRequests, | HasPullRequests: hasPullRequests, | ||||
| IgnoreWhitespaceConflicts: ignoreWhitespaceConflicts, | IgnoreWhitespaceConflicts: ignoreWhitespaceConflicts, | ||||
| AllowMerge: allowMerge, | AllowMerge: allowMerge, | ||||
| @@ -15,6 +15,35 @@ type Permission struct { | |||||
| Pull bool `json:"pull"` | Pull bool `json:"pull"` | ||||
| } | } | ||||
| // InternalTracker represents settings for internal tracker | |||||
| // swagger:model | |||||
| type InternalTracker struct { | |||||
| // Enable time tracking (Built-in issue tracker) | |||||
| EnableTimeTracker bool `json:"enable_time_tracker"` | |||||
| // Let only contributors track time (Built-in issue tracker) | |||||
| AllowOnlyContributorsToTrackTime bool `json:"allow_only_contributors_to_track_time"` | |||||
| // Enable dependencies for issues and pull requests (Built-in issue tracker) | |||||
| EnableIssueDependencies bool `json:"enable_issue_dependencies"` | |||||
| } | |||||
| // ExternalTracker represents settings for external tracker | |||||
| // swagger:model | |||||
| type ExternalTracker struct { | |||||
| // URL of external issue tracker. | |||||
| ExternalTrackerURL string `json:"external_tracker_url"` | |||||
| // External Issue Tracker URL Format. Use the placeholders {user}, {repo} and {index} for the username, repository name and issue index. | |||||
| ExternalTrackerFormat string `json:"external_tracker_format"` | |||||
| // External Issue Tracker Number Format, either `numeric` or `alphanumeric` | |||||
| ExternalTrackerStyle string `json:"external_tracker_style"` | |||||
| } | |||||
| // ExternalWiki represents setting for external wiki | |||||
| // swagger:model | |||||
| type ExternalWiki struct { | |||||
| // URL of external wiki. | |||||
| ExternalWikiURL string `json:"external_wiki_url"` | |||||
| } | |||||
| // Repository represents a repository | // Repository represents a repository | ||||
| type Repository struct { | type Repository struct { | ||||
| ID int64 `json:"id"` | ID int64 `json:"id"` | ||||
| @@ -42,17 +71,20 @@ type Repository struct { | |||||
| // swagger:strfmt date-time | // swagger:strfmt date-time | ||||
| Created time.Time `json:"created_at"` | Created time.Time `json:"created_at"` | ||||
| // swagger:strfmt date-time | // swagger:strfmt date-time | ||||
| Updated time.Time `json:"updated_at"` | |||||
| Permissions *Permission `json:"permissions,omitempty"` | |||||
| HasIssues bool `json:"has_issues"` | |||||
| HasWiki bool `json:"has_wiki"` | |||||
| HasPullRequests bool `json:"has_pull_requests"` | |||||
| IgnoreWhitespaceConflicts bool `json:"ignore_whitespace_conflicts"` | |||||
| AllowMerge bool `json:"allow_merge_commits"` | |||||
| AllowRebase bool `json:"allow_rebase"` | |||||
| AllowRebaseMerge bool `json:"allow_rebase_explicit"` | |||||
| AllowSquash bool `json:"allow_squash_merge"` | |||||
| AvatarURL string `json:"avatar_url"` | |||||
| Updated time.Time `json:"updated_at"` | |||||
| Permissions *Permission `json:"permissions,omitempty"` | |||||
| HasIssues bool `json:"has_issues"` | |||||
| InternalTracker *InternalTracker `json:"internal_tracker,omitempty"` | |||||
| ExternalTracker *ExternalTracker `json:"external_tracker,omitempty"` | |||||
| HasWiki bool `json:"has_wiki"` | |||||
| ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"` | |||||
| HasPullRequests bool `json:"has_pull_requests"` | |||||
| IgnoreWhitespaceConflicts bool `json:"ignore_whitespace_conflicts"` | |||||
| AllowMerge bool `json:"allow_merge_commits"` | |||||
| AllowRebase bool `json:"allow_rebase"` | |||||
| AllowRebaseMerge bool `json:"allow_rebase_explicit"` | |||||
| AllowSquash bool `json:"allow_squash_merge"` | |||||
| AvatarURL string `json:"avatar_url"` | |||||
| } | } | ||||
| // CreateRepoOption options when creating repository | // CreateRepoOption options when creating repository | ||||
| @@ -95,8 +127,14 @@ type EditRepoOption struct { | |||||
| Private *bool `json:"private,omitempty"` | Private *bool `json:"private,omitempty"` | ||||
| // either `true` to enable issues for this repository or `false` to disable them. | // either `true` to enable issues for this repository or `false` to disable them. | ||||
| HasIssues *bool `json:"has_issues,omitempty"` | HasIssues *bool `json:"has_issues,omitempty"` | ||||
| // set this structure to configure internal issue tracker (requires has_issues) | |||||
| InternalTracker *InternalTracker `json:"internal_tracker,omitempty"` | |||||
| // set this structure to use external issue tracker (requires has_issues) | |||||
| ExternalTracker *ExternalTracker `json:"external_tracker,omitempty"` | |||||
| // either `true` to enable the wiki for this repository or `false` to disable it. | // either `true` to enable the wiki for this repository or `false` to disable it. | ||||
| HasWiki *bool `json:"has_wiki,omitempty"` | HasWiki *bool `json:"has_wiki,omitempty"` | ||||
| // set this structure to use external wiki instead of internal (requires has_wiki) | |||||
| ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"` | |||||
| // sets the default branch for this repository. | // sets the default branch for this repository. | ||||
| DefaultBranch *string `json:"default_branch,omitempty"` | DefaultBranch *string `json:"default_branch,omitempty"` | ||||
| // either `true` to allow pull requests, or `false` to prevent pull request. | // either `true` to allow pull requests, or `false` to prevent pull request. | ||||
| @@ -19,6 +19,7 @@ import ( | |||||
| "code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
| api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
| "code.gitea.io/gitea/modules/util" | "code.gitea.io/gitea/modules/util" | ||||
| "code.gitea.io/gitea/modules/validation" | |||||
| "code.gitea.io/gitea/routers/api/v1/convert" | "code.gitea.io/gitea/routers/api/v1/convert" | ||||
| mirror_service "code.gitea.io/gitea/services/mirror" | mirror_service "code.gitea.io/gitea/services/mirror" | ||||
| ) | ) | ||||
| @@ -669,27 +670,56 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { | |||||
| units = append(units, *unit) | units = append(units, *unit) | ||||
| } | } | ||||
| } else if *opts.HasIssues { | } else if *opts.HasIssues { | ||||
| // We don't currently allow setting individual issue settings through the API, | |||||
| // only can enable/disable issues, so when enabling issues, | |||||
| // we either get the existing config which means it was already enabled, | |||||
| // or create a new config since it doesn't exist. | |||||
| unit, err := repo.GetUnit(models.UnitTypeIssues) | |||||
| var config *models.IssuesConfig | |||||
| if err != nil { | |||||
| // Unit type doesn't exist so we make a new config file with default values | |||||
| config = &models.IssuesConfig{ | |||||
| EnableTimetracker: true, | |||||
| AllowOnlyContributorsToTrackTime: true, | |||||
| EnableDependencies: true, | |||||
| if opts.ExternalTracker != nil { | |||||
| // Check that values are valid | |||||
| if !validation.IsValidExternalURL(opts.ExternalTracker.ExternalTrackerURL) { | |||||
| err := fmt.Errorf("External tracker URL not valid") | |||||
| ctx.Error(http.StatusUnprocessableEntity, "Invalid external tracker URL", err) | |||||
| return err | |||||
| } | } | ||||
| if len(opts.ExternalTracker.ExternalTrackerFormat) != 0 && !validation.IsValidExternalTrackerURLFormat(opts.ExternalTracker.ExternalTrackerFormat) { | |||||
| err := fmt.Errorf("External tracker URL format not valid") | |||||
| ctx.Error(http.StatusUnprocessableEntity, "Invalid external tracker URL format", err) | |||||
| return err | |||||
| } | |||||
| units = append(units, models.RepoUnit{ | |||||
| RepoID: repo.ID, | |||||
| Type: models.UnitTypeExternalTracker, | |||||
| Config: &models.ExternalTrackerConfig{ | |||||
| ExternalTrackerURL: opts.ExternalTracker.ExternalTrackerURL, | |||||
| ExternalTrackerFormat: opts.ExternalTracker.ExternalTrackerFormat, | |||||
| ExternalTrackerStyle: opts.ExternalTracker.ExternalTrackerStyle, | |||||
| }, | |||||
| }) | |||||
| } else { | } else { | ||||
| config = unit.IssuesConfig() | |||||
| // Default to built-in tracker | |||||
| var config *models.IssuesConfig | |||||
| if opts.InternalTracker != nil { | |||||
| config = &models.IssuesConfig{ | |||||
| EnableTimetracker: opts.InternalTracker.EnableTimeTracker, | |||||
| AllowOnlyContributorsToTrackTime: opts.InternalTracker.AllowOnlyContributorsToTrackTime, | |||||
| EnableDependencies: opts.InternalTracker.EnableIssueDependencies, | |||||
| } | |||||
| } else if unit, err := repo.GetUnit(models.UnitTypeIssues); err != nil { | |||||
| // Unit type doesn't exist so we make a new config file with default values | |||||
| config = &models.IssuesConfig{ | |||||
| EnableTimetracker: true, | |||||
| AllowOnlyContributorsToTrackTime: true, | |||||
| EnableDependencies: true, | |||||
| } | |||||
| } else { | |||||
| config = unit.IssuesConfig() | |||||
| } | |||||
| units = append(units, models.RepoUnit{ | |||||
| RepoID: repo.ID, | |||||
| Type: models.UnitTypeIssues, | |||||
| Config: config, | |||||
| }) | |||||
| } | } | ||||
| units = append(units, models.RepoUnit{ | |||||
| RepoID: repo.ID, | |||||
| Type: models.UnitTypeIssues, | |||||
| Config: config, | |||||
| }) | |||||
| } | } | ||||
| if opts.HasWiki == nil { | if opts.HasWiki == nil { | ||||
| @@ -700,16 +730,30 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { | |||||
| units = append(units, *unit) | units = append(units, *unit) | ||||
| } | } | ||||
| } else if *opts.HasWiki { | } else if *opts.HasWiki { | ||||
| // We don't currently allow setting individual wiki settings through the API, | |||||
| // only can enable/disable the wiki, so when enabling the wiki, | |||||
| // we either get the existing config which means it was already enabled, | |||||
| // or create a new config since it doesn't exist. | |||||
| config := &models.UnitConfig{} | |||||
| units = append(units, models.RepoUnit{ | |||||
| RepoID: repo.ID, | |||||
| Type: models.UnitTypeWiki, | |||||
| Config: config, | |||||
| }) | |||||
| if opts.ExternalWiki != nil { | |||||
| // Check that values are valid | |||||
| if !validation.IsValidExternalURL(opts.ExternalWiki.ExternalWikiURL) { | |||||
| err := fmt.Errorf("External wiki URL not valid") | |||||
| ctx.Error(http.StatusUnprocessableEntity, "", "Invalid external wiki URL") | |||||
| return err | |||||
| } | |||||
| units = append(units, models.RepoUnit{ | |||||
| RepoID: repo.ID, | |||||
| Type: models.UnitTypeExternalWiki, | |||||
| Config: &models.ExternalWikiConfig{ | |||||
| ExternalWikiURL: opts.ExternalWiki.ExternalWikiURL, | |||||
| }, | |||||
| }) | |||||
| } else { | |||||
| config := &models.UnitConfig{} | |||||
| units = append(units, models.RepoUnit{ | |||||
| RepoID: repo.ID, | |||||
| Type: models.UnitTypeWiki, | |||||
| Config: config, | |||||
| }) | |||||
| } | |||||
| } | } | ||||
| if opts.HasPullRequests == nil { | if opts.HasPullRequests == nil { | ||||
| @@ -8469,6 +8469,12 @@ | |||||
| "type": "string", | "type": "string", | ||||
| "x-go-name": "Description" | "x-go-name": "Description" | ||||
| }, | }, | ||||
| "external_tracker": { | |||||
| "$ref": "#/definitions/ExternalTracker" | |||||
| }, | |||||
| "external_wiki": { | |||||
| "$ref": "#/definitions/ExternalWiki" | |||||
| }, | |||||
| "has_issues": { | "has_issues": { | ||||
| "description": "either `true` to enable issues for this repository or `false` to disable them.", | "description": "either `true` to enable issues for this repository or `false` to disable them.", | ||||
| "type": "boolean", | "type": "boolean", | ||||
| @@ -8489,6 +8495,9 @@ | |||||
| "type": "boolean", | "type": "boolean", | ||||
| "x-go-name": "IgnoreWhitespaceConflicts" | "x-go-name": "IgnoreWhitespaceConflicts" | ||||
| }, | }, | ||||
| "internal_tracker": { | |||||
| "$ref": "#/definitions/InternalTracker" | |||||
| }, | |||||
| "name": { | "name": { | ||||
| "description": "name of the repository", | "description": "name of the repository", | ||||
| "type": "string", | "type": "string", | ||||
| @@ -8644,6 +8653,40 @@ | |||||
| }, | }, | ||||
| "x-go-package": "code.gitea.io/gitea/modules/structs" | "x-go-package": "code.gitea.io/gitea/modules/structs" | ||||
| }, | }, | ||||
| "ExternalTracker": { | |||||
| "description": "ExternalTracker represents settings for external tracker", | |||||
| "type": "object", | |||||
| "properties": { | |||||
| "external_tracker_format": { | |||||
| "description": "External Issue Tracker URL Format. Use the placeholders {user}, {repo} and {index} for the username, repository name and issue index.", | |||||
| "type": "string", | |||||
| "x-go-name": "ExternalTrackerFormat" | |||||
| }, | |||||
| "external_tracker_style": { | |||||
| "description": "External Issue Tracker Number Format, either `numeric` or `alphanumeric`", | |||||
| "type": "string", | |||||
| "x-go-name": "ExternalTrackerStyle" | |||||
| }, | |||||
| "external_tracker_url": { | |||||
| "description": "URL of external issue tracker.", | |||||
| "type": "string", | |||||
| "x-go-name": "ExternalTrackerURL" | |||||
| } | |||||
| }, | |||||
| "x-go-package": "code.gitea.io/gitea/modules/structs" | |||||
| }, | |||||
| "ExternalWiki": { | |||||
| "description": "ExternalWiki represents setting for external wiki", | |||||
| "type": "object", | |||||
| "properties": { | |||||
| "external_wiki_url": { | |||||
| "description": "URL of external wiki.", | |||||
| "type": "string", | |||||
| "x-go-name": "ExternalWikiURL" | |||||
| } | |||||
| }, | |||||
| "x-go-package": "code.gitea.io/gitea/modules/structs" | |||||
| }, | |||||
| "FileCommitResponse": { | "FileCommitResponse": { | ||||
| "type": "object", | "type": "object", | ||||
| "title": "FileCommitResponse contains information generated from a Git commit for a repo's file.", | "title": "FileCommitResponse contains information generated from a Git commit for a repo's file.", | ||||
| @@ -9008,6 +9051,28 @@ | |||||
| }, | }, | ||||
| "x-go-package": "code.gitea.io/gitea/modules/structs" | "x-go-package": "code.gitea.io/gitea/modules/structs" | ||||
| }, | }, | ||||
| "InternalTracker": { | |||||
| "description": "InternalTracker represents settings for internal tracker", | |||||
| "type": "object", | |||||
| "properties": { | |||||
| "allow_only_contributors_to_track_time": { | |||||
| "description": "Let only contributors track time (Built-in issue tracker)", | |||||
| "type": "boolean", | |||||
| "x-go-name": "AllowOnlyContributorsToTrackTime" | |||||
| }, | |||||
| "enable_issue_dependencies": { | |||||
| "description": "Enable dependencies for issues and pull requests (Built-in issue tracker)", | |||||
| "type": "boolean", | |||||
| "x-go-name": "EnableIssueDependencies" | |||||
| }, | |||||
| "enable_time_tracker": { | |||||
| "description": "Enable time tracking (Built-in issue tracker)", | |||||
| "type": "boolean", | |||||
| "x-go-name": "EnableTimeTracker" | |||||
| } | |||||
| }, | |||||
| "x-go-package": "code.gitea.io/gitea/modules/structs" | |||||
| }, | |||||
| "Issue": { | "Issue": { | ||||
| "description": "Issue represents an issue in a repository", | "description": "Issue represents an issue in a repository", | ||||
| "type": "object", | "type": "object", | ||||
| @@ -9863,6 +9928,12 @@ | |||||
| "type": "boolean", | "type": "boolean", | ||||
| "x-go-name": "Empty" | "x-go-name": "Empty" | ||||
| }, | }, | ||||
| "external_tracker": { | |||||
| "$ref": "#/definitions/ExternalTracker" | |||||
| }, | |||||
| "external_wiki": { | |||||
| "$ref": "#/definitions/ExternalWiki" | |||||
| }, | |||||
| "fork": { | "fork": { | ||||
| "type": "boolean", | "type": "boolean", | ||||
| "x-go-name": "Fork" | "x-go-name": "Fork" | ||||
| @@ -9901,6 +9972,9 @@ | |||||
| "type": "boolean", | "type": "boolean", | ||||
| "x-go-name": "IgnoreWhitespaceConflicts" | "x-go-name": "IgnoreWhitespaceConflicts" | ||||
| }, | }, | ||||
| "internal_tracker": { | |||||
| "$ref": "#/definitions/InternalTracker" | |||||
| }, | |||||
| "mirror": { | "mirror": { | ||||
| "type": "boolean", | "type": "boolean", | ||||
| "x-go-name": "Mirror" | "x-go-name": "Mirror" | ||||