feat: add wiki git info to API (#11589)

Add information about the git repository for wiki pages to the
Repository response in the API:

- has_wiki_contents: info whether wiki git repository already exists
- wiki_clone_url: the git clone URL of the wiki git repository
- wiki_ssh_url: the git SSH URL of the wiki git repository

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/11589
Reviewed-by: Gusted <gusted@noreply.codeberg.org>
Co-authored-by: hwipl <hwipl@noreply.codeberg.org>
Co-committed-by: hwipl <hwipl@noreply.codeberg.org>
This commit is contained in:
hwipl 2026-03-19 01:21:50 +01:00 committed by Gusted
commit 5b47f1f002
4 changed files with 109 additions and 29 deletions

View file

@ -80,35 +80,40 @@ type Repository struct {
// swagger:strfmt date-time
Created time.Time `json:"created_at"`
// swagger:strfmt date-time
Updated time.Time `json:"updated_at"`
ArchivedAt time.Time `json:"archived_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"`
WikiBranch string `json:"wiki_branch,omitempty"`
GloballyEditableWiki bool `json:"globally_editable_wiki"`
HasPullRequests bool `json:"has_pull_requests"`
HasProjects bool `json:"has_projects"`
HasReleases bool `json:"has_releases"`
HasPackages bool `json:"has_packages"`
HasActions bool `json:"has_actions"`
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"`
AllowFastForwardOnly bool `json:"allow_fast_forward_only_merge"`
AllowRebaseUpdate bool `json:"allow_rebase_update"`
DefaultDeleteBranchAfterMerge bool `json:"default_delete_branch_after_merge"`
DefaultMergeStyle string `json:"default_merge_style"`
DefaultAllowMaintainerEdit bool `json:"default_allow_maintainer_edit"`
DefaultUpdateStyle string `json:"default_update_style"`
AvatarURL string `json:"avatar_url"`
Internal bool `json:"internal"`
MirrorInterval string `json:"mirror_interval"`
Updated time.Time `json:"updated_at"`
ArchivedAt time.Time `json:"archived_at"`
Permissions *Permission `json:"permissions,omitempty"`
HasIssues bool `json:"has_issues"`
InternalTracker *InternalTracker `json:"internal_tracker,omitempty"`
ExternalTracker *ExternalTracker `json:"external_tracker,omitempty"`
// is the wiki enabled
HasWiki bool `json:"has_wiki"`
// have wiki pages ever been created
HasWikiContents bool `json:"has_wiki_contents"`
ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"`
WikiBranch string `json:"wiki_branch,omitempty"`
WikiSSHURL string `json:"wiki_ssh_url"`
WikiCloneURL string `json:"wiki_clone_url"`
GloballyEditableWiki bool `json:"globally_editable_wiki"`
HasPullRequests bool `json:"has_pull_requests"`
HasProjects bool `json:"has_projects"`
HasReleases bool `json:"has_releases"`
HasPackages bool `json:"has_packages"`
HasActions bool `json:"has_actions"`
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"`
AllowFastForwardOnly bool `json:"allow_fast_forward_only_merge"`
AllowRebaseUpdate bool `json:"allow_rebase_update"`
DefaultDeleteBranchAfterMerge bool `json:"default_delete_branch_after_merge"`
DefaultMergeStyle string `json:"default_merge_style"`
DefaultAllowMaintainerEdit bool `json:"default_allow_maintainer_edit"`
DefaultUpdateStyle string `json:"default_update_style"`
AvatarURL string `json:"avatar_url"`
Internal bool `json:"internal"`
MirrorInterval string `json:"mirror_interval"`
// ObjectFormatName of the underlying git repository
// enum: ["sha1", "sha256"]
ObjectFormatName string `json:"object_format_name"`

View file

@ -227,7 +227,10 @@ func innerToRepo(ctx stdCtx.Context, repo *repo_model.Repository, permissionInRe
ExternalTracker: externalTracker,
InternalTracker: internalTracker,
HasWiki: hasWiki,
HasWikiContents: repo.HasWiki(),
WikiBranch: repo.WikiBranch,
WikiSSHURL: repo.WikiCloneLink().SSH,
WikiCloneURL: repo.WikiCloneLink().HTTPS,
GloballyEditableWiki: globallyEditableWiki,
HasProjects: hasProjects,
HasReleases: hasReleases,

View file

@ -29016,9 +29016,15 @@
"x-go-name": "HasReleases"
},
"has_wiki": {
"description": "is the wiki enabled",
"type": "boolean",
"x-go-name": "HasWiki"
},
"has_wiki_contents": {
"description": "have wiki pages ever been created",
"type": "boolean",
"x-go-name": "HasWikiContents"
},
"html_url": {
"type": "string",
"x-go-name": "HTMLURL"
@ -29158,6 +29164,14 @@
"wiki_branch": {
"type": "string",
"x-go-name": "WikiBranch"
},
"wiki_clone_url": {
"type": "string",
"x-go-name": "WikiCloneURL"
},
"wiki_ssh_url": {
"type": "string",
"x-go-name": "WikiSSHURL"
}
},
"x-go-package": "forgejo.org/modules/structs"

View file

@ -1049,6 +1049,64 @@ func TestAPIViewRepoObjectFormat(t *testing.T) {
assert.Equal(t, "sha1", repo.ObjectFormatName)
}
// TestAPIViewRepoWikiGitInfo tests wiki git information
func TestAPIViewRepoWikiGitInfo(t *testing.T) {
defer tests.PrepareTestEnv(t)()
for _, test := range []struct {
name string
user string
repo string
hasWiki bool
hasContents bool
}{
{
name: "wiki enabled, wiki contents",
user: "user2",
repo: "repo1",
hasWiki: true,
hasContents: true,
},
{
name: "wiki enabled, no wiki contents",
user: "user5",
repo: "repo4",
hasWiki: true,
hasContents: false,
},
{
name: "wiki disabled, no wiki contents",
user: "user12",
repo: "repo10",
hasWiki: false,
hasContents: false,
},
} {
t.Run(test.name, func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
// get repo
url := fmt.Sprintf("/api/v1/repos/%s/%s", test.user, test.repo)
req := NewRequest(t, "GET", url)
resp := MakeRequest(t, req, http.StatusOK)
var repo api.Repository
DecodeJSON(t, resp, &repo)
// check repo
sshURL := fmt.Sprintf("ssh://%s@%s:%d/%s/%s.wiki.git",
setting.SSH.User, setting.SSH.Domain, setting.SSH.Port,
test.user, test.repo)
cloneURL := fmt.Sprintf("http://%s:%s/%s/%s.wiki.git",
setting.Domain, setting.HTTPPort,
test.user, test.repo)
assert.Equal(t, test.hasWiki, repo.HasWiki)
assert.Equal(t, test.hasContents, repo.HasWikiContents)
assert.Equal(t, sshURL, repo.WikiSSHURL)
assert.Equal(t, cloneURL, repo.WikiCloneURL)
})
}
}
func TestAPIRepoCommitPull(t *testing.T) {
defer tests.PrepareTestEnv(t)()