Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Api: advanced settings for repository (external wiki, issue tracker etc.) #7756

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 139 additions & 15 deletions integrations/api_repo_edit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
lafriks marked this conversation as resolved.
Show resolved Hide resolved
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
Expand All @@ -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,
}
}

Expand Down Expand Up @@ -143,6 +177,96 @@ 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)

// 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
*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)
Expand Down
102 changes: 68 additions & 34 deletions models/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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),
}
}

Expand Down
49 changes: 38 additions & 11 deletions modules/structs/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
lafriks marked this conversation as resolved.
Show resolved Hide resolved
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
Expand Down Expand Up @@ -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.
Expand Down
Loading