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