From 7e5c9536c7b30168f9231a5bfd6b1cddae0708b4 Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Sat, 10 Aug 2019 19:00:24 +0200 Subject: [PATCH 1/9] Add API for Repo Advanced Settings of wiki and issue tracker Signed-off-by: David Svantesson --- models/repo.go | 102 +++++++++++++++++--------- modules/structs/repo.go | 49 ++++++++++--- routers/api/v1/repo/repo.go | 130 ++++++++++++++++++++++++++------- templates/swagger/v1_json.tmpl | 81 ++++++++++++++++++++ 4 files changed, 289 insertions(+), 73 deletions(-) diff --git a/models/repo.go b/models/repo.go index 86370821d3bb0..a060c54335dbc 100644 --- a/models/repo.go +++ b/models/repo.go @@ -275,12 +275,37 @@ func (repo *Repository) innerAPIFormat(e Engine, mode AccessMode, isParent bool) } } hasIssues := false - if _, err := repo.getUnit(e, UnitTypeIssues); err == nil { + externalTracker := false + externalTrackerURL := "" + externalTrackerFormat := "" + externalTrackerStyle := "" + enableTimeTracker := false + letOnlyContributorsTrackTime := false + enableIssueDependencies := false + if unit, err := repo.getUnit(e, UnitTypeIssues); err == nil { + config := unit.IssuesConfig() hasIssues = true + enableTimeTracker = config.EnableTimetracker + letOnlyContributorsTrackTime = config.AllowOnlyContributorsToTrackTime + enableIssueDependencies = config.EnableDependencies + } else if unit, err := repo.getUnit(e, UnitTypeExternalTracker); err == nil { + config := unit.ExternalTrackerConfig() + hasIssues = true + externalTracker = true + externalTrackerURL = config.ExternalTrackerURL + externalTrackerFormat = config.ExternalTrackerFormat + externalTrackerStyle = config.ExternalTrackerStyle } hasWiki := false + externalWiki := false + externalWikiURL := "" 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 = true + externalWikiURL = config.ExternalWikiURL } hasPullRequests := false ignoreWhitespaceConflicts := false @@ -299,39 +324,48 @@ func (repo *Repository) innerAPIFormat(e Engine, mode AccessMode, isParent bool) } return &api.Repository{ - ID: repo.ID, - Owner: repo.Owner.APIFormat(), - Name: repo.Name, - FullName: repo.FullName(), - Description: repo.Description, - Private: repo.IsPrivate, - Empty: repo.IsEmpty, - Archived: repo.IsArchived, - Size: int(repo.Size / 1024), - Fork: repo.IsFork, - Parent: parent, - Mirror: repo.IsMirror, - HTMLURL: repo.HTMLURL(), - SSHURL: cloneLink.SSH, - CloneURL: cloneLink.HTTPS, - Website: repo.Website, - Stars: repo.NumStars, - Forks: repo.NumForks, - Watchers: repo.NumWatches, - OpenIssues: repo.NumOpenIssues, - DefaultBranch: repo.DefaultBranch, - Created: repo.CreatedUnix.AsTime(), - Updated: repo.UpdatedUnix.AsTime(), - Permissions: permission, - HasIssues: hasIssues, - HasWiki: hasWiki, - HasPullRequests: hasPullRequests, - IgnoreWhitespaceConflicts: ignoreWhitespaceConflicts, - AllowMerge: allowMerge, - AllowRebase: allowRebase, - AllowRebaseMerge: allowRebaseMerge, - AllowSquash: allowSquash, - AvatarURL: repo.avatarLink(e), + ID: repo.ID, + Owner: repo.Owner.APIFormat(), + Name: repo.Name, + FullName: repo.FullName(), + Description: repo.Description, + Private: repo.IsPrivate, + Empty: repo.IsEmpty, + Archived: repo.IsArchived, + Size: int(repo.Size / 1024), + Fork: repo.IsFork, + Parent: parent, + Mirror: repo.IsMirror, + HTMLURL: repo.HTMLURL(), + SSHURL: cloneLink.SSH, + CloneURL: cloneLink.HTTPS, + Website: repo.Website, + Stars: repo.NumStars, + Forks: repo.NumForks, + Watchers: repo.NumWatches, + OpenIssues: repo.NumOpenIssues, + DefaultBranch: repo.DefaultBranch, + Created: repo.CreatedUnix.AsTime(), + Updated: repo.UpdatedUnix.AsTime(), + Permissions: permission, + HasIssues: hasIssues, + ExternalTracker: externalTracker, + ExternalTrackerURL: externalTrackerURL, + ExternalTrackerFormat: externalTrackerFormat, + ExternalTrackerStyle: externalTrackerStyle, + EnableTimeTracker: enableTimeTracker, + LetOnlyContributorsTrackTime: letOnlyContributorsTrackTime, + EnableIssueDependencies: enableIssueDependencies, + HasWiki: hasWiki, + ExternalWiki: externalWiki, + ExternalWikiURL: externalWikiURL, + HasPullRequests: hasPullRequests, + IgnoreWhitespaceConflicts: ignoreWhitespaceConflicts, + AllowMerge: allowMerge, + AllowRebase: allowRebase, + AllowRebaseMerge: allowRebaseMerge, + AllowSquash: allowSquash, + AvatarURL: repo.avatarLink(e), } } diff --git a/modules/structs/repo.go b/modules/structs/repo.go index 81203319e01bb..9b7a52b939734 100644 --- a/modules/structs/repo.go +++ b/modules/structs/repo.go @@ -42,17 +42,26 @@ 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"` + ExternalTracker bool `json:"external_tracker"` + ExternalTrackerURL string `json:"external_tracker_url"` + ExternalTrackerFormat string `json:"external_tracker_format"` + ExternalTrackerStyle string `json:"external_tracker_style"` + EnableTimeTracker bool `json:"enable_time_tracker"` + LetOnlyContributorsTrackTime bool `json:"let_only_contributors_track_time"` + EnableIssueDependencies bool `json:"enable_issue_dependencies"` + HasWiki bool `json:"has_wiki"` + ExternalWiki bool `json:"external_wiki"` + ExternalWikiURL string `json:"external_wiki_url"` + 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 @@ -93,8 +102,26 @@ 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"` + // either `true` to enable external issue tracker or `false` to disable it. + ExternalTracker *bool `json:"external_tracker,omitempty"` + // URL of external issue tracker. + ExternalTrackerURL *string `json:"external_tracker_url,omitempty"` + // 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,omitempty"` + // External Issue Tracker Number Format, either `numeric` or `alphanumeric` + ExternalTrackerStyle *string `json:"external_tracker_style,omitempty"` + // Enable time tracking (Built-in issue tracker) + EnableTimeTracker *bool `json:"enable_time_tracker,omitempty"` + // Let only contributors track time (Built-in issue tracker) + LetOnlyContributorsTrackTime *bool `json:"let_only_contributors_track_time,omitempty"` + // Enable dependencies for issues and pull requests (Built-in issue tracker) + EnableIssueDependencies *bool `json:"enable_issue_dependencies,omitempty"` // either `true` to enable the wiki for this repository or `false` to disable it. HasWiki *bool `json:"has_wiki,omitempty"` + // either `true` to enable external wiki or `false` to disable it. + ExternalWiki *bool `json:"external_wiki,omitempty"` + // URL of external wiki. + ExternalWikiURL *string `json:"external_wiki_url,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. diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 8d7e43edff8cf..bd201eaf900f7 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -18,6 +18,7 @@ import ( "code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/validation" "code.gitea.io/gitea/routers/api/v1/convert" api "code.gitea.io/gitea/modules/structs" @@ -659,27 +660,77 @@ 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 && *opts.ExternalTracker { + + var config *models.ExternalTrackerConfig + if unit, err := repo.GetUnit(models.UnitTypeExternalTracker); err != nil { + // Unit type doesn't exist so we make a new config file, default empty strings + config = &models.ExternalTrackerConfig{ + ExternalTrackerURL: "", + ExternalTrackerFormat: "", + ExternalTrackerStyle: "", + } + } else { + config = unit.ExternalTrackerConfig() + } + + // Update values if set and valid + if opts.ExternalTrackerURL != nil { + if !validation.IsValidExternalURL(*opts.ExternalTrackerURL) { + err := fmt.Errorf("External tracker URL not valid") + ctx.Error(http.StatusBadRequest, "Invalid external tracker URL", err) + return err + } + config.ExternalTrackerURL = *opts.ExternalTrackerURL + } + if opts.ExternalTrackerFormat != nil { + if len(*opts.ExternalTrackerFormat) != 0 && !validation.IsValidExternalTrackerURLFormat(*opts.ExternalTrackerFormat) { + err := fmt.Errorf("External tracker URL format not valid") + ctx.Error(http.StatusBadRequest, "Invalid external tracker URL format", err) + return err + } + config.ExternalTrackerFormat = *opts.ExternalTrackerFormat + } + if opts.ExternalTrackerStyle != nil { + config.ExternalTrackerStyle = *opts.ExternalTrackerStyle } + + units = append(units, models.RepoUnit{ + RepoID: repo.ID, + Type: models.UnitTypeExternalTracker, + Config: config, + }) } else { - config = unit.IssuesConfig() + // Default to built-in tracker + var config *models.IssuesConfig + 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() + } + + // Update values if set + if opts.EnableTimeTracker != nil { + config.EnableTimetracker = *opts.EnableTimeTracker + } + if opts.LetOnlyContributorsTrackTime != nil { + config.AllowOnlyContributorsToTrackTime = *opts.LetOnlyContributorsTrackTime + } + if opts.EnableIssueDependencies != nil { + config.EnableDependencies = *opts.EnableIssueDependencies + } + + 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 { @@ -690,16 +741,39 @@ 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 && *opts.ExternalWiki { + var config *models.ExternalWikiConfig + if unit, err := repo.GetUnit(models.UnitTypeExternalWiki); err != nil { + // Unit type doesn't exist so we make a new config file, default empty strings + config = &models.ExternalWikiConfig{ + ExternalWikiURL: "", + } + } else { + config = unit.ExternalWikiConfig() + } + + // Update values if set and valid + if opts.ExternalWikiURL != nil { + if !validation.IsValidExternalURL(*opts.ExternalWikiURL) { + err := fmt.Errorf("External wiki URL not valid") + ctx.Error(http.StatusBadRequest, "", "Invalid external wiki URL") + return err + } + config.ExternalWikiURL = *opts.ExternalWikiURL + } + units = append(units, models.RepoUnit{ + RepoID: repo.ID, + Type: models.UnitTypeExternalWiki, + Config: config, + }) + } else { + config := &models.UnitConfig{} + units = append(units, models.RepoUnit{ + RepoID: repo.ID, + Type: models.UnitTypeWiki, + Config: config, + }) + } } if opts.HasPullRequests == nil { diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 4ae7f5a49ebfe..9b31dc3cdeccc 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -8133,6 +8133,46 @@ "type": "string", "x-go-name": "Description" }, + "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" + }, + "external_tracker": { + "description": "either `true` to enable external issue tracker or `false` to disable it.", + "type": "boolean", + "x-go-name": "ExternalTracker" + }, + "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" + }, + "external_wiki": { + "description": "either `true` to enable external wiki or `false` to disable it.", + "type": "boolean", + "x-go-name": "ExternalWiki" + }, + "external_wiki_url": { + "description": "URL of external wiki.", + "type": "string", + "x-go-name": "ExternalWikiURL" + }, "has_issues": { "description": "either `true` to enable issues for this repository or `false` to disable them.", "type": "boolean", @@ -8153,6 +8193,11 @@ "type": "boolean", "x-go-name": "IgnoreWhitespaceConflicts" }, + "let_only_contributors_track_time": { + "description": "Let only contributors track time (Built-in issue tracker)", + "type": "boolean", + "x-go-name": "LetOnlyContributorsTrackTime" + }, "name": { "description": "name of the repository", "type": "string", @@ -9508,6 +9553,38 @@ "type": "boolean", "x-go-name": "Empty" }, + "enable_issue_dependencies": { + "type": "boolean", + "x-go-name": "EnableIssueDependencies" + }, + "enable_time_tracker": { + "type": "boolean", + "x-go-name": "EnableTimeTracker" + }, + "external_tracker": { + "type": "boolean", + "x-go-name": "ExternalTracker" + }, + "external_tracker_format": { + "type": "string", + "x-go-name": "ExternalTrackerFormat" + }, + "external_tracker_style": { + "type": "string", + "x-go-name": "ExternalTrackerStyle" + }, + "external_tracker_url": { + "type": "string", + "x-go-name": "ExternalTrackerURL" + }, + "external_wiki": { + "type": "boolean", + "x-go-name": "ExternalWiki" + }, + "external_wiki_url": { + "type": "string", + "x-go-name": "ExternalWikiURL" + }, "fork": { "type": "boolean", "x-go-name": "Fork" @@ -9546,6 +9623,10 @@ "type": "boolean", "x-go-name": "IgnoreWhitespaceConflicts" }, + "let_only_contributors_track_time": { + "type": "boolean", + "x-go-name": "LetOnlyContributorsTrackTime" + }, "mirror": { "type": "boolean", "x-go-name": "Mirror" From 2085fa2ccab4ca27be132be4a0ee494e75ac20b8 Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Sun, 11 Aug 2019 20:33:23 +0200 Subject: [PATCH 2/9] Add some integration tests for tracker and wiki settings through API --- integrations/api_repo_edit_test.go | 139 +++++++++++++++++++++++++---- 1 file changed, 124 insertions(+), 15 deletions(-) diff --git a/integrations/api_repo_edit_test.go b/integrations/api_repo_edit_test.go index 1231201b978fe..721266a5c6298 100644 --- a/integrations/api_repo_edit_test.go +++ b/integrations/api_repo_edit_test.go @@ -23,12 +23,37 @@ func getRepoEditOptionFromRepo(repo *models.Repository) *api.EditRepoOption { website := repo.Website private := repo.IsPrivate hasIssues := false - if _, err := repo.GetUnit(models.UnitTypeIssues); err == nil { + externalTracker := false + externalTrackerURL := "" + externalTrackerFormat := "" + externalTrackerStyle := "" + enableTimeTracker := false + letOnlyContributorsTrackTime := false + enableIssueDependencies := false + if unit, err := repo.GetUnit(models.UnitTypeIssues); err == nil { + config := unit.IssuesConfig() hasIssues = true + enableTimeTracker = config.EnableTimetracker + letOnlyContributorsTrackTime = config.AllowOnlyContributorsToTrackTime + enableIssueDependencies = config.EnableDependencies + } else if unit, err := repo.GetUnit(models.UnitTypeExternalTracker); err == nil { + config := unit.ExternalTrackerConfig() + hasIssues = true + externalTracker = true + externalTrackerURL = config.ExternalTrackerURL + externalTrackerFormat = config.ExternalTrackerFormat + externalTrackerStyle = config.ExternalTrackerStyle } hasWiki := false + externalWiki := false + externalWikiURL := "" 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 = true + externalWikiURL = config.ExternalWikiURL } defaultBranch := repo.DefaultBranch hasPullRequests := false @@ -48,20 +73,29 @@ func getRepoEditOptionFromRepo(repo *models.Repository) *api.EditRepoOption { } archived := repo.IsArchived return &api.EditRepoOption{ - Name: &name, - Description: &description, - Website: &website, - Private: &private, - HasIssues: &hasIssues, - HasWiki: &hasWiki, - DefaultBranch: &defaultBranch, - HasPullRequests: &hasPullRequests, - IgnoreWhitespaceConflicts: &ignoreWhitespaceConflicts, - AllowMerge: &allowMerge, - AllowRebase: &allowRebase, - AllowRebaseMerge: &allowRebaseMerge, - AllowSquash: &allowSquash, - Archived: &archived, + Name: &name, + Description: &description, + Website: &website, + Private: &private, + HasIssues: &hasIssues, + ExternalTracker: &externalTracker, + ExternalTrackerURL: &externalTrackerURL, + ExternalTrackerFormat: &externalTrackerFormat, + ExternalTrackerStyle: &externalTrackerStyle, + EnableTimeTracker: &enableTimeTracker, + LetOnlyContributorsTrackTime: &letOnlyContributorsTrackTime, + EnableIssueDependencies: &enableIssueDependencies, + HasWiki: &hasWiki, + ExternalWiki: &externalWiki, + ExternalWikiURL: &externalWikiURL, + DefaultBranch: &defaultBranch, + HasPullRequests: &hasPullRequests, + IgnoreWhitespaceConflicts: &ignoreWhitespaceConflicts, + AllowMerge: &allowMerge, + AllowRebase: &allowRebase, + AllowRebaseMerge: &allowRebaseMerge, + AllowSquash: &allowSquash, + Archived: &archived, } } @@ -143,6 +177,81 @@ 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) + enableTimeTracker := false + letOnlyContributorsTrackTime := false + enableIssueDependencies := false + *repoEditOption.HasIssues = true + repoEditOption.ExternalTracker = nil + repoEditOption.EnableTimeTracker = &enableTimeTracker + repoEditOption.LetOnlyContributorsTrackTime = &letOnlyContributorsTrackTime + repoEditOption.EnableIssueDependencies = &enableIssueDependencies + *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.Equal(t, *repo1editedOption.ExternalTracker, false) + assert.Equal(t, *repo1editedOption.EnableTimeTracker, false) + assert.Equal(t, *repo1editedOption.LetOnlyContributorsTrackTime, false) + assert.Equal(t, *repo1editedOption.EnableIssueDependencies, false) + assert.Equal(t, *repo1editedOption.HasWiki, true) + assert.Equal(t, *repo1editedOption.ExternalWiki, false) + + //Test editing repo1 to use external issue and wiki + externalTracker := true + externalURL := "http://www.somewebsite.com" + externalTrackerFormat := "http://www.somewebsite.com/{user}/{repo}?issue={index}" + externalTrackerStyle := "alphanumeric" + externalWiki := true + repoEditOption.ExternalTracker = &externalTracker + repoEditOption.ExternalTrackerURL = &externalURL + repoEditOption.ExternalTrackerFormat = &externalTrackerFormat + repoEditOption.ExternalTrackerStyle = &externalTrackerStyle + repoEditOption.ExternalWiki = &externalWiki + repoEditOption.ExternalWikiURL = &externalURL + 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, true) + assert.Equal(t, *repo1editedOption.ExternalTrackerURL, *repoEditOption.ExternalTrackerURL) + assert.Equal(t, *repo1editedOption.ExternalTrackerFormat, *repoEditOption.ExternalTrackerFormat) + assert.Equal(t, *repo1editedOption.ExternalTrackerStyle, *repoEditOption.ExternalTrackerStyle) + assert.Equal(t, *repo1editedOption.HasWiki, true) + assert.Equal(t, *repo1editedOption.ExternalWiki, true) + assert.Equal(t, *repo1editedOption.ExternalWikiURL, *repoEditOption.ExternalWikiURL) + + //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 = false + repoEditOption.HasWiki = nil + *repoEditOption.ExternalWiki = false + 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.Equal(t, *repo1editedOption.ExternalTracker, true) + assert.Equal(t, *repo1editedOption.HasWiki, true) + assert.Equal(t, *repo1editedOption.ExternalWiki, true) + // 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) From 075ce3543fef5e44af248e9caf2ce1a45bd80a3e Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Sun, 11 Aug 2019 22:31:38 +0200 Subject: [PATCH 3/9] Should return StatusUnprocessableEntity in case of invalid API values. --- routers/api/v1/repo/repo.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index bd201eaf900f7..28845510b77d9 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -678,7 +678,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { if opts.ExternalTrackerURL != nil { if !validation.IsValidExternalURL(*opts.ExternalTrackerURL) { err := fmt.Errorf("External tracker URL not valid") - ctx.Error(http.StatusBadRequest, "Invalid external tracker URL", err) + ctx.Error(http.StatusUnprocessableEntity, "Invalid external tracker URL", err) return err } config.ExternalTrackerURL = *opts.ExternalTrackerURL @@ -686,7 +686,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { if opts.ExternalTrackerFormat != nil { if len(*opts.ExternalTrackerFormat) != 0 && !validation.IsValidExternalTrackerURLFormat(*opts.ExternalTrackerFormat) { err := fmt.Errorf("External tracker URL format not valid") - ctx.Error(http.StatusBadRequest, "Invalid external tracker URL format", err) + ctx.Error(http.StatusUnprocessableEntity, "Invalid external tracker URL format", err) return err } config.ExternalTrackerFormat = *opts.ExternalTrackerFormat @@ -756,7 +756,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { if opts.ExternalWikiURL != nil { if !validation.IsValidExternalURL(*opts.ExternalWikiURL) { err := fmt.Errorf("External wiki URL not valid") - ctx.Error(http.StatusBadRequest, "", "Invalid external wiki URL") + ctx.Error(http.StatusUnprocessableEntity, "", "Invalid external wiki URL") return err } config.ExternalWikiURL = *opts.ExternalWikiURL From b8f81a3ac8346756f38778f52002ce5e95887490 Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Sun, 11 Aug 2019 22:46:18 +0200 Subject: [PATCH 4/9] Add tests for invalid URLs for external tracker and wiki. --- integrations/api_repo_edit_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/integrations/api_repo_edit_test.go b/integrations/api_repo_edit_test.go index 721266a5c6298..971f0ec0030f6 100644 --- a/integrations/api_repo_edit_test.go +++ b/integrations/api_repo_edit_test.go @@ -233,6 +233,21 @@ func TestAPIRepoEdit(t *testing.T) { assert.Equal(t, *repo1editedOption.ExternalWiki, true) assert.Equal(t, *repo1editedOption.ExternalWikiURL, *repoEditOption.ExternalWikiURL) + // Do some tests with invalid URL for external tracker and wiki + externalURLInvalid := "htp://www.somewebsite.com" + externalTrackerFormatInvalid := "http://www.somewebsite.com/{user/{repo}?issue={index}" + repoEditOption.ExternalTrackerURL = &externalURLInvalid + req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption) + resp = session.MakeRequest(t, req, http.StatusUnprocessableEntity) + repoEditOption.ExternalTrackerURL = &externalURL + repoEditOption.ExternalTrackerFormat = &externalTrackerFormatInvalid + req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption) + resp = session.MakeRequest(t, req, http.StatusUnprocessableEntity) + repoEditOption.ExternalTrackerFormat = &externalTrackerFormat + repoEditOption.ExternalWikiURL = &externalURLInvalid + 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 From 5df6dcaefa5cfff7ee33e1ea26b7e5d69d341d32 Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Mon, 12 Aug 2019 19:44:31 +0000 Subject: [PATCH 5/9] Do not set inital values if they are default of type --- routers/api/v1/repo/repo.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 28845510b77d9..8963a58798da6 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -665,11 +665,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { var config *models.ExternalTrackerConfig if unit, err := repo.GetUnit(models.UnitTypeExternalTracker); err != nil { // Unit type doesn't exist so we make a new config file, default empty strings - config = &models.ExternalTrackerConfig{ - ExternalTrackerURL: "", - ExternalTrackerFormat: "", - ExternalTrackerStyle: "", - } + config = &models.ExternalTrackerConfig{} } else { config = unit.ExternalTrackerConfig() } @@ -745,9 +741,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { var config *models.ExternalWikiConfig if unit, err := repo.GetUnit(models.UnitTypeExternalWiki); err != nil { // Unit type doesn't exist so we make a new config file, default empty strings - config = &models.ExternalWikiConfig{ - ExternalWikiURL: "", - } + config = &models.ExternalWikiConfig{} } else { config = unit.ExternalWikiConfig() } From d474ae7b3fe633cee03fbf8118d9fb1af34693c5 Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Sat, 14 Sep 2019 11:37:23 +0200 Subject: [PATCH 6/9] Make issue tracker and wiki units separate structures in Repository API structure. Signed-off-by: David Svantesson --- models/repo.go | 112 +++++++++++++++------------------ modules/structs/repo.go | 53 ++++++++++------ templates/swagger/v1_json.tmpl | 84 ++++++++++++++++--------- 3 files changed, 138 insertions(+), 111 deletions(-) diff --git a/models/repo.go b/models/repo.go index a060c54335dbc..6bee84c81fe52 100644 --- a/models/repo.go +++ b/models/repo.go @@ -275,37 +275,35 @@ func (repo *Repository) innerAPIFormat(e Engine, mode AccessMode, isParent bool) } } hasIssues := false - externalTracker := false - externalTrackerURL := "" - externalTrackerFormat := "" - externalTrackerStyle := "" - enableTimeTracker := false - letOnlyContributorsTrackTime := false - enableIssueDependencies := false + var externalTracker *api.ExternalTracker + var internalTracker *api.InternalTracker if unit, err := repo.getUnit(e, UnitTypeIssues); err == nil { config := unit.IssuesConfig() hasIssues = true - enableTimeTracker = config.EnableTimetracker - letOnlyContributorsTrackTime = config.AllowOnlyContributorsToTrackTime - enableIssueDependencies = config.EnableDependencies + internalTracker = &api.InternalTracker{ + EnableTimeTracker: config.EnableTimetracker, + LetOnlyContributorsTrackTime: config.AllowOnlyContributorsToTrackTime, + EnableIssueDependencies: config.EnableDependencies, + } } else if unit, err := repo.getUnit(e, UnitTypeExternalTracker); err == nil { config := unit.ExternalTrackerConfig() hasIssues = true - externalTracker = true - externalTrackerURL = config.ExternalTrackerURL - externalTrackerFormat = config.ExternalTrackerFormat - externalTrackerStyle = config.ExternalTrackerStyle + externalTracker = &api.ExternalTracker{ + ExternalTrackerURL: config.ExternalTrackerURL, + ExternalTrackerFormat: config.ExternalTrackerFormat, + ExternalTrackerStyle: config.ExternalTrackerStyle, + } } hasWiki := false - externalWiki := false - externalWikiURL := "" + 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 = true - externalWikiURL = config.ExternalWikiURL + externalWiki = &api.ExternalWiki{ + ExternalWikiURL: config.ExternalWikiURL, + } } hasPullRequests := false ignoreWhitespaceConflicts := false @@ -324,48 +322,42 @@ func (repo *Repository) innerAPIFormat(e Engine, mode AccessMode, isParent bool) } return &api.Repository{ - ID: repo.ID, - Owner: repo.Owner.APIFormat(), - Name: repo.Name, - FullName: repo.FullName(), - Description: repo.Description, - Private: repo.IsPrivate, - Empty: repo.IsEmpty, - Archived: repo.IsArchived, - Size: int(repo.Size / 1024), - Fork: repo.IsFork, - Parent: parent, - Mirror: repo.IsMirror, - HTMLURL: repo.HTMLURL(), - SSHURL: cloneLink.SSH, - CloneURL: cloneLink.HTTPS, - Website: repo.Website, - Stars: repo.NumStars, - Forks: repo.NumForks, - Watchers: repo.NumWatches, - OpenIssues: repo.NumOpenIssues, - DefaultBranch: repo.DefaultBranch, - Created: repo.CreatedUnix.AsTime(), - Updated: repo.UpdatedUnix.AsTime(), - Permissions: permission, - HasIssues: hasIssues, - ExternalTracker: externalTracker, - ExternalTrackerURL: externalTrackerURL, - ExternalTrackerFormat: externalTrackerFormat, - ExternalTrackerStyle: externalTrackerStyle, - EnableTimeTracker: enableTimeTracker, - LetOnlyContributorsTrackTime: letOnlyContributorsTrackTime, - EnableIssueDependencies: enableIssueDependencies, - HasWiki: hasWiki, - ExternalWiki: externalWiki, - ExternalWikiURL: externalWikiURL, - HasPullRequests: hasPullRequests, - IgnoreWhitespaceConflicts: ignoreWhitespaceConflicts, - AllowMerge: allowMerge, - AllowRebase: allowRebase, - AllowRebaseMerge: allowRebaseMerge, - AllowSquash: allowSquash, - AvatarURL: repo.avatarLink(e), + ID: repo.ID, + Owner: repo.Owner.APIFormat(), + Name: repo.Name, + FullName: repo.FullName(), + Description: repo.Description, + Private: repo.IsPrivate, + Empty: repo.IsEmpty, + Archived: repo.IsArchived, + Size: int(repo.Size / 1024), + Fork: repo.IsFork, + Parent: parent, + Mirror: repo.IsMirror, + HTMLURL: repo.HTMLURL(), + SSHURL: cloneLink.SSH, + CloneURL: cloneLink.HTTPS, + Website: repo.Website, + Stars: repo.NumStars, + Forks: repo.NumForks, + Watchers: repo.NumWatches, + OpenIssues: repo.NumOpenIssues, + DefaultBranch: repo.DefaultBranch, + Created: repo.CreatedUnix.AsTime(), + Updated: repo.UpdatedUnix.AsTime(), + Permissions: permission, + HasIssues: hasIssues, + ExternalTracker: externalTracker, + InternalTracker: internalTracker, + HasWiki: hasWiki, + ExternalWiki: externalWiki, + HasPullRequests: hasPullRequests, + IgnoreWhitespaceConflicts: ignoreWhitespaceConflicts, + AllowMerge: allowMerge, + AllowRebase: allowRebase, + AllowRebaseMerge: allowRebaseMerge, + AllowSquash: allowSquash, + AvatarURL: repo.avatarLink(e), } } diff --git a/modules/structs/repo.go b/modules/structs/repo.go index 9b7a52b939734..16d6585498b6f 100644 --- a/modules/structs/repo.go +++ b/modules/structs/repo.go @@ -15,6 +15,25 @@ type Permission struct { Pull bool `json:"pull"` } +// Represents settings for internal tracker +type InternalTracker struct { + EnableTimeTracker bool `json:"enable_time_tracker"` + LetOnlyContributorsTrackTime bool `json:"let_only_contributors_track_time"` + EnableIssueDependencies bool `json:"enable_issue_dependencies"` +} + +// Represents settings for external tracker +type ExternalTracker struct { + ExternalTrackerURL string `json:"external_tracker_url"` + ExternalTrackerFormat string `json:"external_tracker_format"` + ExternalTrackerStyle string `json:"external_tracker_style"` +} + +// Represents setting for external wiki +type ExternalWiki struct { + ExternalWikiURL string `json:"external_wiki_url"` +} + // Repository represents a repository type Repository struct { ID int64 `json:"id"` @@ -42,26 +61,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"` - ExternalTracker bool `json:"external_tracker"` - ExternalTrackerURL string `json:"external_tracker_url"` - ExternalTrackerFormat string `json:"external_tracker_format"` - ExternalTrackerStyle string `json:"external_tracker_style"` - EnableTimeTracker bool `json:"enable_time_tracker"` - LetOnlyContributorsTrackTime bool `json:"let_only_contributors_track_time"` - EnableIssueDependencies bool `json:"enable_issue_dependencies"` - HasWiki bool `json:"has_wiki"` - ExternalWiki bool `json:"external_wiki"` - ExternalWikiURL string `json:"external_wiki_url"` - 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 diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 9b31dc3cdeccc..fea91e5a9c24f 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -8353,6 +8353,36 @@ }, "x-go-package": "code.gitea.io/gitea/modules/structs" }, + "ExternalTracker": { + "description": "Represents settings for external tracker", + "type": "object", + "properties": { + "external_tracker_format": { + "type": "string", + "x-go-name": "ExternalTrackerFormat" + }, + "external_tracker_style": { + "type": "string", + "x-go-name": "ExternalTrackerStyle" + }, + "external_tracker_url": { + "type": "string", + "x-go-name": "ExternalTrackerURL" + } + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" + }, + "ExternalWiki": { + "description": "Represents setting for external wiki", + "type": "object", + "properties": { + "external_wiki_url": { + "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.", @@ -8717,6 +8747,25 @@ }, "x-go-package": "code.gitea.io/gitea/modules/structs" }, + "InternalTracker": { + "description": "Represents settings for internal tracker", + "type": "object", + "properties": { + "enable_issue_dependencies": { + "type": "boolean", + "x-go-name": "EnableIssueDependencies" + }, + "enable_time_tracker": { + "type": "boolean", + "x-go-name": "EnableTimeTracker" + }, + "let_only_contributors_track_time": { + "type": "boolean", + "x-go-name": "LetOnlyContributorsTrackTime" + } + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" + }, "Issue": { "description": "Issue represents an issue in a repository", "type": "object", @@ -9553,37 +9602,11 @@ "type": "boolean", "x-go-name": "Empty" }, - "enable_issue_dependencies": { - "type": "boolean", - "x-go-name": "EnableIssueDependencies" - }, - "enable_time_tracker": { - "type": "boolean", - "x-go-name": "EnableTimeTracker" - }, "external_tracker": { - "type": "boolean", - "x-go-name": "ExternalTracker" - }, - "external_tracker_format": { - "type": "string", - "x-go-name": "ExternalTrackerFormat" - }, - "external_tracker_style": { - "type": "string", - "x-go-name": "ExternalTrackerStyle" - }, - "external_tracker_url": { - "type": "string", - "x-go-name": "ExternalTrackerURL" + "$ref": "#/definitions/ExternalTracker" }, "external_wiki": { - "type": "boolean", - "x-go-name": "ExternalWiki" - }, - "external_wiki_url": { - "type": "string", - "x-go-name": "ExternalWikiURL" + "$ref": "#/definitions/ExternalWiki" }, "fork": { "type": "boolean", @@ -9623,9 +9646,8 @@ "type": "boolean", "x-go-name": "IgnoreWhitespaceConflicts" }, - "let_only_contributors_track_time": { - "type": "boolean", - "x-go-name": "LetOnlyContributorsTrackTime" + "internal_tracker": { + "$ref": "#/definitions/InternalTracker" }, "mirror": { "type": "boolean", From 791117bdbc86374c7a13043c3963eb4dbc588d4d Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Sat, 14 Sep 2019 12:45:54 +0000 Subject: [PATCH 7/9] Fix comment of structures Signed-off-by: David Svantesson --- modules/structs/repo.go | 6 +++--- templates/swagger/v1_json.tmpl | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/structs/repo.go b/modules/structs/repo.go index 16d6585498b6f..c9835047a67a2 100644 --- a/modules/structs/repo.go +++ b/modules/structs/repo.go @@ -15,21 +15,21 @@ type Permission struct { Pull bool `json:"pull"` } -// Represents settings for internal tracker +// InternalTracker represents settings for internal tracker type InternalTracker struct { EnableTimeTracker bool `json:"enable_time_tracker"` LetOnlyContributorsTrackTime bool `json:"let_only_contributors_track_time"` EnableIssueDependencies bool `json:"enable_issue_dependencies"` } -// Represents settings for external tracker +// ExternalTracker represents settings for external tracker type ExternalTracker struct { ExternalTrackerURL string `json:"external_tracker_url"` ExternalTrackerFormat string `json:"external_tracker_format"` ExternalTrackerStyle string `json:"external_tracker_style"` } -// Represents setting for external wiki +// ExternalWiki represents setting for external wiki type ExternalWiki struct { ExternalWikiURL string `json:"external_wiki_url"` } diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index fea91e5a9c24f..60d47d119f7c0 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -8354,7 +8354,7 @@ "x-go-package": "code.gitea.io/gitea/modules/structs" }, "ExternalTracker": { - "description": "Represents settings for external tracker", + "description": "ExternalTracker represents settings for external tracker", "type": "object", "properties": { "external_tracker_format": { @@ -8373,7 +8373,7 @@ "x-go-package": "code.gitea.io/gitea/modules/structs" }, "ExternalWiki": { - "description": "Represents setting for external wiki", + "description": "ExternalWiki represents setting for external wiki", "type": "object", "properties": { "external_wiki_url": { @@ -8748,7 +8748,7 @@ "x-go-package": "code.gitea.io/gitea/modules/structs" }, "InternalTracker": { - "description": "Represents settings for internal tracker", + "description": "InternalTracker represents settings for internal tracker", "type": "object", "properties": { "enable_issue_dependencies": { From 610c6de1aeb0040695384cf62f7463dc62bbb4a5 Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Sun, 29 Sep 2019 19:33:59 +0200 Subject: [PATCH 8/9] Rewrite API to use struct for setting tracker and wiki settings. --- integrations/api_repo_edit_test.go | 140 +++++++++++++---------------- modules/structs/repo.go | 42 +++++---- routers/api/v1/repo/repo.go | 90 +++++++------------ templates/swagger/v1_json.tmpl | 51 +++-------- 4 files changed, 124 insertions(+), 199 deletions(-) diff --git a/integrations/api_repo_edit_test.go b/integrations/api_repo_edit_test.go index 971f0ec0030f6..1a2ec08074be4 100644 --- a/integrations/api_repo_edit_test.go +++ b/integrations/api_repo_edit_test.go @@ -23,37 +23,35 @@ func getRepoEditOptionFromRepo(repo *models.Repository) *api.EditRepoOption { website := repo.Website private := repo.IsPrivate hasIssues := false - externalTracker := false - externalTrackerURL := "" - externalTrackerFormat := "" - externalTrackerStyle := "" - enableTimeTracker := false - letOnlyContributorsTrackTime := false - enableIssueDependencies := false + var internalTracker *api.InternalTracker + var externalTracker *api.ExternalTracker if unit, err := repo.GetUnit(models.UnitTypeIssues); err == nil { config := unit.IssuesConfig() hasIssues = true - enableTimeTracker = config.EnableTimetracker - letOnlyContributorsTrackTime = config.AllowOnlyContributorsToTrackTime - enableIssueDependencies = config.EnableDependencies + internalTracker = &api.InternalTracker{ + EnableTimeTracker: config.EnableTimetracker, + LetOnlyContributorsTrackTime: config.AllowOnlyContributorsToTrackTime, + EnableIssueDependencies: config.EnableDependencies, + } } else if unit, err := repo.GetUnit(models.UnitTypeExternalTracker); err == nil { config := unit.ExternalTrackerConfig() hasIssues = true - externalTracker = true - externalTrackerURL = config.ExternalTrackerURL - externalTrackerFormat = config.ExternalTrackerFormat - externalTrackerStyle = config.ExternalTrackerStyle + externalTracker = &api.ExternalTracker{ + ExternalTrackerURL: config.ExternalTrackerURL, + ExternalTrackerFormat: config.ExternalTrackerFormat, + ExternalTrackerStyle: config.ExternalTrackerStyle, + } } hasWiki := false - externalWiki := false - externalWikiURL := "" + 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 = true - externalWikiURL = config.ExternalWikiURL + externalWiki = &api.ExternalWiki{ + ExternalWikiURL: config.ExternalWikiURL, + } } defaultBranch := repo.DefaultBranch hasPullRequests := false @@ -73,29 +71,23 @@ func getRepoEditOptionFromRepo(repo *models.Repository) *api.EditRepoOption { } archived := repo.IsArchived return &api.EditRepoOption{ - Name: &name, - Description: &description, - Website: &website, - Private: &private, - HasIssues: &hasIssues, - ExternalTracker: &externalTracker, - ExternalTrackerURL: &externalTrackerURL, - ExternalTrackerFormat: &externalTrackerFormat, - ExternalTrackerStyle: &externalTrackerStyle, - EnableTimeTracker: &enableTimeTracker, - LetOnlyContributorsTrackTime: &letOnlyContributorsTrackTime, - EnableIssueDependencies: &enableIssueDependencies, - HasWiki: &hasWiki, - ExternalWiki: &externalWiki, - ExternalWikiURL: &externalWikiURL, - DefaultBranch: &defaultBranch, - HasPullRequests: &hasPullRequests, - IgnoreWhitespaceConflicts: &ignoreWhitespaceConflicts, - AllowMerge: &allowMerge, - AllowRebase: &allowRebase, - AllowRebaseMerge: &allowRebaseMerge, - AllowSquash: &allowSquash, - Archived: &archived, + Name: &name, + Description: &description, + Website: &website, + Private: &private, + HasIssues: &hasIssues, + ExternalTracker: externalTracker, + InternalTracker: internalTracker, + HasWiki: &hasWiki, + ExternalWiki: externalWiki, + DefaultBranch: &defaultBranch, + HasPullRequests: &hasPullRequests, + IgnoreWhitespaceConflicts: &ignoreWhitespaceConflicts, + AllowMerge: &allowMerge, + AllowRebase: &allowRebase, + AllowRebaseMerge: &allowRebaseMerge, + AllowSquash: &allowSquash, + Archived: &archived, } } @@ -179,14 +171,13 @@ func TestAPIRepoEdit(t *testing.T) { assert.Equal(t, *repoEditOption.HasWiki, *repo1editedOption.HasWiki) //Test editing repo1 to use internal issue and wiki (default) - enableTimeTracker := false - letOnlyContributorsTrackTime := false - enableIssueDependencies := false *repoEditOption.HasIssues = true repoEditOption.ExternalTracker = nil - repoEditOption.EnableTimeTracker = &enableTimeTracker - repoEditOption.LetOnlyContributorsTrackTime = &letOnlyContributorsTrackTime - repoEditOption.EnableIssueDependencies = &enableIssueDependencies + repoEditOption.InternalTracker = &api.InternalTracker{ + EnableTimeTracker: false, + LetOnlyContributorsTrackTime: false, + EnableIssueDependencies: false, + } *repoEditOption.HasWiki = true repoEditOption.ExternalWiki = nil url = fmt.Sprintf("/api/v1/repos/%s/%s?token=%s", user2.Name, *repoEditOption.Name, token2) @@ -198,25 +189,20 @@ func TestAPIRepoEdit(t *testing.T) { repo1edited = models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) repo1editedOption = getRepoEditOptionFromRepo(repo1edited) assert.Equal(t, *repo1editedOption.HasIssues, true) - assert.Equal(t, *repo1editedOption.ExternalTracker, false) - assert.Equal(t, *repo1editedOption.EnableTimeTracker, false) - assert.Equal(t, *repo1editedOption.LetOnlyContributorsTrackTime, false) - assert.Equal(t, *repo1editedOption.EnableIssueDependencies, false) + assert.Nil(t, repo1editedOption.ExternalTracker) + assert.Equal(t, *repo1editedOption.InternalTracker, *repoEditOption.InternalTracker) assert.Equal(t, *repo1editedOption.HasWiki, true) - assert.Equal(t, *repo1editedOption.ExternalWiki, false) + assert.Nil(t, repo1editedOption.ExternalWiki) //Test editing repo1 to use external issue and wiki - externalTracker := true - externalURL := "http://www.somewebsite.com" - externalTrackerFormat := "http://www.somewebsite.com/{user}/{repo}?issue={index}" - externalTrackerStyle := "alphanumeric" - externalWiki := true - repoEditOption.ExternalTracker = &externalTracker - repoEditOption.ExternalTrackerURL = &externalURL - repoEditOption.ExternalTrackerFormat = &externalTrackerFormat - repoEditOption.ExternalTrackerStyle = &externalTrackerStyle - repoEditOption.ExternalWiki = &externalWiki - repoEditOption.ExternalWikiURL = &externalURL + 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) @@ -225,35 +211,29 @@ func TestAPIRepoEdit(t *testing.T) { repo1edited = models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) repo1editedOption = getRepoEditOptionFromRepo(repo1edited) assert.Equal(t, *repo1editedOption.HasIssues, true) - assert.Equal(t, *repo1editedOption.ExternalTracker, true) - assert.Equal(t, *repo1editedOption.ExternalTrackerURL, *repoEditOption.ExternalTrackerURL) - assert.Equal(t, *repo1editedOption.ExternalTrackerFormat, *repoEditOption.ExternalTrackerFormat) - assert.Equal(t, *repo1editedOption.ExternalTrackerStyle, *repoEditOption.ExternalTrackerStyle) + assert.Equal(t, *repo1editedOption.ExternalTracker, *repoEditOption.ExternalTracker) assert.Equal(t, *repo1editedOption.HasWiki, true) - assert.Equal(t, *repo1editedOption.ExternalWiki, true) - assert.Equal(t, *repo1editedOption.ExternalWikiURL, *repoEditOption.ExternalWikiURL) + assert.Equal(t, *repo1editedOption.ExternalWiki, *repoEditOption.ExternalWiki) // Do some tests with invalid URL for external tracker and wiki - externalURLInvalid := "htp://www.somewebsite.com" - externalTrackerFormatInvalid := "http://www.somewebsite.com/{user/{repo}?issue={index}" - repoEditOption.ExternalTrackerURL = &externalURLInvalid + repoEditOption.ExternalTracker.ExternalTrackerURL = "htp://www.somewebsite.com" req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption) resp = session.MakeRequest(t, req, http.StatusUnprocessableEntity) - repoEditOption.ExternalTrackerURL = &externalURL - repoEditOption.ExternalTrackerFormat = &externalTrackerFormatInvalid + 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.ExternalTrackerFormat = &externalTrackerFormat - repoEditOption.ExternalWikiURL = &externalURLInvalid + 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 = false + repoEditOption.ExternalTracker = nil repoEditOption.HasWiki = nil - *repoEditOption.ExternalWiki = false + repoEditOption.ExternalWiki = nil req = NewRequestWithJSON(t, "PATCH", url, &repoEditOption) resp = session.MakeRequest(t, req, http.StatusOK) DecodeJSON(t, resp, &repo) @@ -263,9 +243,9 @@ func TestAPIRepoEdit(t *testing.T) { repo1editedOption = getRepoEditOptionFromRepo(repo1edited) assert.Equal(t, *repo1editedOption.Description, *repoEditOption.Description) assert.Equal(t, *repo1editedOption.HasIssues, true) - assert.Equal(t, *repo1editedOption.ExternalTracker, true) + assert.NotNil(t, *repo1editedOption.ExternalTracker) assert.Equal(t, *repo1editedOption.HasWiki, true) - assert.Equal(t, *repo1editedOption.ExternalWiki, 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) diff --git a/modules/structs/repo.go b/modules/structs/repo.go index e2fe31d9cec52..995ed80ccdc97 100644 --- a/modules/structs/repo.go +++ b/modules/structs/repo.go @@ -16,21 +16,31 @@ type Permission struct { } // InternalTracker represents settings for internal tracker +// swagger:model type InternalTracker struct { - EnableTimeTracker bool `json:"enable_time_tracker"` + // Enable time tracking (Built-in issue tracker) + EnableTimeTracker bool `json:"enable_time_tracker"` + // Let only contributors track time (Built-in issue tracker) LetOnlyContributorsTrackTime bool `json:"let_only_contributors_track_time"` - EnableIssueDependencies bool `json:"enable_issue_dependencies"` + // 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 { - ExternalTrackerURL string `json:"external_tracker_url"` + // 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"` - ExternalTrackerStyle string `json:"external_tracker_style"` + // 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"` } @@ -117,26 +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"` - // either `true` to enable external issue tracker or `false` to disable it. - ExternalTracker *bool `json:"external_tracker,omitempty"` - // URL of external issue tracker. - ExternalTrackerURL *string `json:"external_tracker_url,omitempty"` - // 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,omitempty"` - // External Issue Tracker Number Format, either `numeric` or `alphanumeric` - ExternalTrackerStyle *string `json:"external_tracker_style,omitempty"` - // Enable time tracking (Built-in issue tracker) - EnableTimeTracker *bool `json:"enable_time_tracker,omitempty"` - // Let only contributors track time (Built-in issue tracker) - LetOnlyContributorsTrackTime *bool `json:"let_only_contributors_track_time,omitempty"` - // Enable dependencies for issues and pull requests (Built-in issue tracker) - EnableIssueDependencies *bool `json:"enable_issue_dependencies,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"` - // either `true` to enable external wiki or `false` to disable it. - ExternalWiki *bool `json:"external_wiki,omitempty"` - // URL of external wiki. - ExternalWikiURL *string `json:"external_wiki_url,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. diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index e5624d77f213f..3d550aa58ffaa 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -669,46 +669,40 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { units = append(units, *unit) } } else if *opts.HasIssues { - if opts.ExternalTracker != nil && *opts.ExternalTracker { + if opts.ExternalTracker != nil { - var config *models.ExternalTrackerConfig - if unit, err := repo.GetUnit(models.UnitTypeExternalTracker); err != nil { - // Unit type doesn't exist so we make a new config file, default empty strings - config = &models.ExternalTrackerConfig{} - } else { - config = unit.ExternalTrackerConfig() - } - - // Update values if set and valid - if opts.ExternalTrackerURL != nil { - if !validation.IsValidExternalURL(*opts.ExternalTrackerURL) { - err := fmt.Errorf("External tracker URL not valid") - ctx.Error(http.StatusUnprocessableEntity, "Invalid external tracker URL", err) - return err - } - config.ExternalTrackerURL = *opts.ExternalTrackerURL - } - if opts.ExternalTrackerFormat != nil { - if len(*opts.ExternalTrackerFormat) != 0 && !validation.IsValidExternalTrackerURLFormat(*opts.ExternalTrackerFormat) { - err := fmt.Errorf("External tracker URL format not valid") - ctx.Error(http.StatusUnprocessableEntity, "Invalid external tracker URL format", err) - return err - } - config.ExternalTrackerFormat = *opts.ExternalTrackerFormat + // 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 opts.ExternalTrackerStyle != nil { - config.ExternalTrackerStyle = *opts.ExternalTrackerStyle + 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: config, + Config: &models.ExternalTrackerConfig{ + ExternalTrackerURL: opts.ExternalTracker.ExternalTrackerURL, + ExternalTrackerFormat: opts.ExternalTracker.ExternalTrackerFormat, + ExternalTrackerStyle: opts.ExternalTracker.ExternalTrackerStyle, + }, }) } else { // Default to built-in tracker var config *models.IssuesConfig - if unit, err := repo.GetUnit(models.UnitTypeIssues); err != nil { + + if opts.InternalTracker != nil { + config = &models.IssuesConfig{ + EnableTimetracker: opts.InternalTracker.EnableTimeTracker, + AllowOnlyContributorsToTrackTime: opts.InternalTracker.LetOnlyContributorsTrackTime, + 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, @@ -719,17 +713,6 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { config = unit.IssuesConfig() } - // Update values if set - if opts.EnableTimeTracker != nil { - config.EnableTimetracker = *opts.EnableTimeTracker - } - if opts.LetOnlyContributorsTrackTime != nil { - config.AllowOnlyContributorsToTrackTime = *opts.LetOnlyContributorsTrackTime - } - if opts.EnableIssueDependencies != nil { - config.EnableDependencies = *opts.EnableIssueDependencies - } - units = append(units, models.RepoUnit{ RepoID: repo.ID, Type: models.UnitTypeIssues, @@ -746,28 +729,21 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { units = append(units, *unit) } } else if *opts.HasWiki { - if opts.ExternalWiki != nil && *opts.ExternalWiki { - var config *models.ExternalWikiConfig - if unit, err := repo.GetUnit(models.UnitTypeExternalWiki); err != nil { - // Unit type doesn't exist so we make a new config file, default empty strings - config = &models.ExternalWikiConfig{} - } else { - config = unit.ExternalWikiConfig() - } + if opts.ExternalWiki != nil { - // Update values if set and valid - if opts.ExternalWikiURL != nil { - if !validation.IsValidExternalURL(*opts.ExternalWikiURL) { - err := fmt.Errorf("External wiki URL not valid") - ctx.Error(http.StatusUnprocessableEntity, "", "Invalid external wiki URL") - return err - } - config.ExternalWikiURL = *opts.ExternalWikiURL + // 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: config, + Config: &models.ExternalWikiConfig{ + ExternalWikiURL: opts.ExternalWiki.ExternalWikiURL, + }, }) } else { config := &models.UnitConfig{} diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index c5a2429189f09..dacdd8ca1843c 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -8397,45 +8397,11 @@ "type": "string", "x-go-name": "Description" }, - "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" - }, "external_tracker": { - "description": "either `true` to enable external issue tracker or `false` to disable it.", - "type": "boolean", - "x-go-name": "ExternalTracker" - }, - "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" + "$ref": "#/definitions/ExternalTracker" }, "external_wiki": { - "description": "either `true` to enable external wiki or `false` to disable it.", - "type": "boolean", - "x-go-name": "ExternalWiki" - }, - "external_wiki_url": { - "description": "URL of external wiki.", - "type": "string", - "x-go-name": "ExternalWikiURL" + "$ref": "#/definitions/ExternalWiki" }, "has_issues": { "description": "either `true` to enable issues for this repository or `false` to disable them.", @@ -8457,10 +8423,8 @@ "type": "boolean", "x-go-name": "IgnoreWhitespaceConflicts" }, - "let_only_contributors_track_time": { - "description": "Let only contributors track time (Built-in issue tracker)", - "type": "boolean", - "x-go-name": "LetOnlyContributorsTrackTime" + "internal_tracker": { + "$ref": "#/definitions/InternalTracker" }, "name": { "description": "name of the repository", @@ -8622,14 +8586,17 @@ "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" } @@ -8641,6 +8608,7 @@ "type": "object", "properties": { "external_wiki_url": { + "description": "URL of external wiki.", "type": "string", "x-go-name": "ExternalWikiURL" } @@ -9016,14 +8984,17 @@ "type": "object", "properties": { "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" }, "let_only_contributors_track_time": { + "description": "Let only contributors track time (Built-in issue tracker)", "type": "boolean", "x-go-name": "LetOnlyContributorsTrackTime" } From d90ae6ac69faa5ce7684687d76863b85dfdf1ff5 Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Mon, 30 Sep 2019 07:21:48 +0200 Subject: [PATCH 9/9] LetOnlyContributorsTrackTime -> AllowOnlyContributorsToTrackTime --- integrations/api_repo_edit_test.go | 12 ++++++------ models/repo.go | 6 +++--- modules/structs/repo.go | 2 +- routers/api/v1/repo/repo.go | 2 +- templates/swagger/v1_json.tmpl | 10 +++++----- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/integrations/api_repo_edit_test.go b/integrations/api_repo_edit_test.go index 1a2ec08074be4..c1b513d0753c1 100644 --- a/integrations/api_repo_edit_test.go +++ b/integrations/api_repo_edit_test.go @@ -29,9 +29,9 @@ func getRepoEditOptionFromRepo(repo *models.Repository) *api.EditRepoOption { config := unit.IssuesConfig() hasIssues = true internalTracker = &api.InternalTracker{ - EnableTimeTracker: config.EnableTimetracker, - LetOnlyContributorsTrackTime: config.AllowOnlyContributorsToTrackTime, - EnableIssueDependencies: config.EnableDependencies, + EnableTimeTracker: config.EnableTimetracker, + AllowOnlyContributorsToTrackTime: config.AllowOnlyContributorsToTrackTime, + EnableIssueDependencies: config.EnableDependencies, } } else if unit, err := repo.GetUnit(models.UnitTypeExternalTracker); err == nil { config := unit.ExternalTrackerConfig() @@ -174,9 +174,9 @@ func TestAPIRepoEdit(t *testing.T) { *repoEditOption.HasIssues = true repoEditOption.ExternalTracker = nil repoEditOption.InternalTracker = &api.InternalTracker{ - EnableTimeTracker: false, - LetOnlyContributorsTrackTime: false, - EnableIssueDependencies: false, + EnableTimeTracker: false, + AllowOnlyContributorsToTrackTime: false, + EnableIssueDependencies: false, } *repoEditOption.HasWiki = true repoEditOption.ExternalWiki = nil diff --git a/models/repo.go b/models/repo.go index a61224d0d1d8b..d624b82ddaca1 100644 --- a/models/repo.go +++ b/models/repo.go @@ -281,9 +281,9 @@ func (repo *Repository) innerAPIFormat(e Engine, mode AccessMode, isParent bool) config := unit.IssuesConfig() hasIssues = true internalTracker = &api.InternalTracker{ - EnableTimeTracker: config.EnableTimetracker, - LetOnlyContributorsTrackTime: config.AllowOnlyContributorsToTrackTime, - EnableIssueDependencies: config.EnableDependencies, + EnableTimeTracker: config.EnableTimetracker, + AllowOnlyContributorsToTrackTime: config.AllowOnlyContributorsToTrackTime, + EnableIssueDependencies: config.EnableDependencies, } } else if unit, err := repo.getUnit(e, UnitTypeExternalTracker); err == nil { config := unit.ExternalTrackerConfig() diff --git a/modules/structs/repo.go b/modules/structs/repo.go index 995ed80ccdc97..87396d6ce99a9 100644 --- a/modules/structs/repo.go +++ b/modules/structs/repo.go @@ -21,7 +21,7 @@ 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) - LetOnlyContributorsTrackTime bool `json:"let_only_contributors_track_time"` + 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"` } diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 3d550aa58ffaa..93ced989cc234 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -699,7 +699,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { if opts.InternalTracker != nil { config = &models.IssuesConfig{ EnableTimetracker: opts.InternalTracker.EnableTimeTracker, - AllowOnlyContributorsToTrackTime: opts.InternalTracker.LetOnlyContributorsTrackTime, + AllowOnlyContributorsToTrackTime: opts.InternalTracker.AllowOnlyContributorsToTrackTime, EnableDependencies: opts.InternalTracker.EnableIssueDependencies, } } else if unit, err := repo.GetUnit(models.UnitTypeIssues); err != nil { diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index d2f8029a42063..f89d780e68c38 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -8991,6 +8991,11 @@ "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", @@ -9000,11 +9005,6 @@ "description": "Enable time tracking (Built-in issue tracker)", "type": "boolean", "x-go-name": "EnableTimeTracker" - }, - "let_only_contributors_track_time": { - "description": "Let only contributors track time (Built-in issue tracker)", - "type": "boolean", - "x-go-name": "LetOnlyContributorsTrackTime" } }, "x-go-package": "code.gitea.io/gitea/modules/structs"