* 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 | |||
| private := repo.IsPrivate | |||
| 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 | |||
| 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 | |||
| var externalWiki *api.ExternalWiki | |||
| if _, err := repo.GetUnit(models.UnitTypeWiki); err == nil { | |||
| 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 | |||
| hasPullRequests := false | |||
| @@ -53,7 +76,10 @@ func getRepoEditOptionFromRepo(repo *models.Repository) *api.EditRepoOption { | |||
| Website: &website, | |||
| Private: &private, | |||
| HasIssues: &hasIssues, | |||
| ExternalTracker: externalTracker, | |||
| InternalTracker: internalTracker, | |||
| HasWiki: &hasWiki, | |||
| ExternalWiki: externalWiki, | |||
| DefaultBranch: &defaultBranch, | |||
| HasPullRequests: &hasPullRequests, | |||
| IgnoreWhitespaceConflicts: &ignoreWhitespaceConflicts, | |||
| @@ -143,6 +169,84 @@ func TestAPIRepoEdit(t *testing.T) { | |||
| assert.Equal(t, *repoEditOption.Archived, *repo1editedOption.Archived) | |||
| assert.Equal(t, *repoEditOption.Private, *repo1editedOption.Private) | |||
| 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 | |||
| url = fmt.Sprintf("/api/v1/repos/%s/%s?token=%s", user2.Name, *repoEditOption.Name, token2) | |||
| req = NewRequestWithJSON(t, "PATCH", url, &origRepoEditOption) | |||
| @@ -275,12 +275,35 @@ func (repo *Repository) innerAPIFormat(e Engine, mode AccessMode, isParent bool) | |||
| } | |||
| } | |||
| 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 | |||
| 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 | |||
| var externalWiki *api.ExternalWiki | |||
| if _, err := repo.getUnit(e, UnitTypeWiki); err == nil { | |||
| 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 | |||
| ignoreWhitespaceConflicts := false | |||
| @@ -324,7 +347,10 @@ func (repo *Repository) innerAPIFormat(e Engine, mode AccessMode, isParent bool) | |||
| Updated: repo.UpdatedUnix.AsTime(), | |||
| Permissions: permission, | |||
| HasIssues: hasIssues, | |||
| ExternalTracker: externalTracker, | |||
| InternalTracker: internalTracker, | |||
| HasWiki: hasWiki, | |||
| ExternalWiki: externalWiki, | |||
| HasPullRequests: hasPullRequests, | |||
| IgnoreWhitespaceConflicts: ignoreWhitespaceConflicts, | |||
| AllowMerge: allowMerge, | |||
| @@ -15,6 +15,35 @@ type Permission struct { | |||
| 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 | |||
| type Repository struct { | |||
| ID int64 `json:"id"` | |||
| @@ -42,17 +71,20 @@ type Repository struct { | |||
| // swagger:strfmt date-time | |||
| Created time.Time `json:"created_at"` | |||
| // 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 | |||
| @@ -95,8 +127,14 @@ type EditRepoOption struct { | |||
| Private *bool `json:"private,omitempty"` | |||
| // either `true` to enable issues for this repository or `false` to disable them. | |||
| 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. | |||
| 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. | |||
| DefaultBranch *string `json:"default_branch,omitempty"` | |||
| // either `true` to allow pull requests, or `false` to prevent pull request. | |||
| @@ -19,6 +19,7 @@ import ( | |||
| "code.gitea.io/gitea/modules/setting" | |||
| api "code.gitea.io/gitea/modules/structs" | |||
| "code.gitea.io/gitea/modules/util" | |||
| "code.gitea.io/gitea/modules/validation" | |||
| "code.gitea.io/gitea/routers/api/v1/convert" | |||
| 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) | |||
| } | |||
| } 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 { | |||
| 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 { | |||
| @@ -700,16 +730,30 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { | |||
| units = append(units, *unit) | |||
| } | |||
| } 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 { | |||
| @@ -8469,6 +8469,12 @@ | |||
| "type": "string", | |||
| "x-go-name": "Description" | |||
| }, | |||
| "external_tracker": { | |||
| "$ref": "#/definitions/ExternalTracker" | |||
| }, | |||
| "external_wiki": { | |||
| "$ref": "#/definitions/ExternalWiki" | |||
| }, | |||
| "has_issues": { | |||
| "description": "either `true` to enable issues for this repository or `false` to disable them.", | |||
| "type": "boolean", | |||
| @@ -8489,6 +8495,9 @@ | |||
| "type": "boolean", | |||
| "x-go-name": "IgnoreWhitespaceConflicts" | |||
| }, | |||
| "internal_tracker": { | |||
| "$ref": "#/definitions/InternalTracker" | |||
| }, | |||
| "name": { | |||
| "description": "name of the repository", | |||
| "type": "string", | |||
| @@ -8644,6 +8653,40 @@ | |||
| }, | |||
| "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": { | |||
| "type": "object", | |||
| "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" | |||
| }, | |||
| "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": { | |||
| "description": "Issue represents an issue in a repository", | |||
| "type": "object", | |||
| @@ -9863,6 +9928,12 @@ | |||
| "type": "boolean", | |||
| "x-go-name": "Empty" | |||
| }, | |||
| "external_tracker": { | |||
| "$ref": "#/definitions/ExternalTracker" | |||
| }, | |||
| "external_wiki": { | |||
| "$ref": "#/definitions/ExternalWiki" | |||
| }, | |||
| "fork": { | |||
| "type": "boolean", | |||
| "x-go-name": "Fork" | |||
| @@ -9901,6 +9972,9 @@ | |||
| "type": "boolean", | |||
| "x-go-name": "IgnoreWhitespaceConflicts" | |||
| }, | |||
| "internal_tracker": { | |||
| "$ref": "#/definitions/InternalTracker" | |||
| }, | |||
| "mirror": { | |||
| "type": "boolean", | |||
| "x-go-name": "Mirror" | |||