feat(wiki): rename pages with --title alone, page lists on the client

wiki edit P --title New failed with "supply --body": renaming now keeps
the page's content, and edit needs one of --title, --body, --body-file
or --editor. wiki list --limit 1 returned every page because Gitea
replaces a limit of 1 with its default; the page list is now read whole
and paged on the client, so --limit and --page hold and the context line
counts the pages.

wiki create takes the title as an argument and, without --body, asks for
the content in the editor or an inline multi-line field. wiki view shows
the author, last update and revision count above the rendered page, and
--web opens it. wiki list and revisions show headed columns, page names
complete with Tab, and every change reports a ✓ line.

Signed-off-by: bircni <bircni@icloud.com>
This commit is contained in:
bircni committed 2026-10-11 23:52:33 +02:00
1 parent 78b5ff3a19
commit e093610ade
6 files changed
+400 -143

No files matched your search

+22 -8
View File
@@ -82,27 +82,41 @@ func (s Wiki) page(ctx context.Context, op repoOperation[*gitea.WikiPage]) (Wiki
// List returns a non-nil page of wiki metadata.
func (s Wiki) List(ctx context.Context, limit, page int) ([]WikiPage, error) {
pages, err := repoCall(ctx, s.Client, s.Repository, func(ctx context.Context, c *gitea.Client, owner, repo string) ([]*gitea.WikiPageMetaData, *gitea.Response, error) {
return c.Wiki.ListPages(ctx, owner, repo, gitea.ListWikiPagesOptions{ListOptions: listOptions(limit, page)})
window, err := s.ListPage(ctx, limit, page)
return window.Items, err
}
// wikiPageSize is the page size for reading the whole wiki; Gitea replaces a limit of 1 with its
// default page size.
const wikiPageSize = 50
// ListPage is List that also reports whether more pages follow and how many there are. It reads
// the whole page list and pages it on the client, because the server pages it inconsistently.
func (s Wiki) ListPage(ctx context.Context, limit, page int) (Page[WikiPage], error) {
all, err := listAll(func(page int) ([]*gitea.WikiPageMetaData, error) {
return repoCall(ctx, s.Client, s.Repository, func(ctx context.Context, c *gitea.Client, owner, repo string) ([]*gitea.WikiPageMetaData, *gitea.Response, error) {
return c.Wiki.ListPages(ctx, owner, repo, gitea.ListWikiPagesOptions{ListOptions: listOptions(wikiPageSize, page)})
})
})
if err != nil {
if apiError, ok := errors.AsType[*transport.APIError](err); !ok || apiError.Status != http.StatusNotFound {
return nil, err
return Page[WikiPage]{}, err
}
// An uninitialized wiki returns 404. Verify repository visibility and
// wiki configuration before treating that response as an empty list.
repository, checkErr := (Repositories{Client: s.Client}).get(ctx, s.Repository)
if checkErr != nil {
return nil, checkErr
return Page[WikiPage]{}, checkErr
}
if !repository.HasWiki {
return nil, err
return Page[WikiPage]{}, err
}
return []WikiPage{}, nil
return Page[WikiPage]{Items: []WikiPage{}, Counted: true}, nil
}
return convertAll(pages, func(item *gitea.WikiPageMetaData) WikiPage {
items, err := pageOf(convertAll(all, func(item *gitea.WikiPageMetaData) WikiPage {
return wikiPageFrom(item.Title, item.HTMLURL, item.LastCommit)
}), nil
}), limit, page)
return Page[WikiPage]{Items: items, More: page*limit < len(all), Total: len(all), Counted: true}, err
}
// View retrieves and decodes a wiki page.
+13 -7
View File
@@ -75,9 +75,12 @@ func TestWikiListAndRevisionsMapCommits(t *testing.T) {
client := newTestClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/api/v1/repos/alice/project/wiki/pages":
assert.Equal(t, "5", r.URL.Query().Get("limit"))
assert.Equal(t, "2", r.URL.Query().Get("page"))
_, _ = w.Write([]byte(`[{"title":"Home","html_url":"https://gitea.test/wiki/Home","last_commit":{"sha":"abc","author":{"name":"Alice","email":"author@example.test","date":"2026-10-04T00:00:00Z"}}},{"title":"Draft"}]`))
assert.Equal(t, "50", r.URL.Query().Get("limit"))
if r.URL.Query().Get("page") != "1" {
_, _ = w.Write([]byte(`[]`))
return
}
_, _ = w.Write([]byte(`[{"title":"Other"},{"title":"Home","html_url":"https://gitea.test/wiki/Home","last_commit":{"sha":"abc","author":{"name":"Alice","email":"author@example.test","date":"2026-10-04T00:00:00Z"}}},{"title":"Draft"}]`))
case "/api/v1/repos/alice/project/wiki/revisions/Home":
assert.Equal(t, "3", r.URL.Query().Get("page"))
_, _ = w.Write([]byte(`{"commits":[{"sha":"abc","message":"Edit","author":{"name":"Alice","email":"author@example.test","date":"2026-10-04T00:00:00Z"}},{"sha":"def","author":null}],"count":2}`))
@@ -86,12 +89,15 @@ func TestWikiListAndRevisionsMapCommits(t *testing.T) {
}
}))
service := Wiki{Client: client, Repository: "alice/project"}
pages, err := service.List(context.Background(), 5, 2)
pages, err := service.ListPage(context.Background(), 2, 1)
require.NoError(t, err)
require.Equal(t, []WikiPage{
require.Equal(t, Page[WikiPage]{Items: []WikiPage{
{Title: "Other"},
{Title: "Home", URL: "https://gitea.test/wiki/Home", SHA: "abc", Author: "Alice", UpdatedAt: "2026-10-04T00:00:00Z"},
{Title: "Draft"},
}, pages)
}, More: true, Total: 3, Counted: true}, pages)
last, err := service.List(context.Background(), 2, 2)
require.NoError(t, err)
require.Equal(t, []WikiPage{{Title: "Draft"}}, last)
revisions, err := service.Revisions(context.Background(), "Home", 3)
require.NoError(t, err)
require.Equal(t, []WikiRevision{{SHA: "abc", Message: "Edit", Author: "Alice", CreatedAt: "2026-10-04T00:00:00Z"}, {SHA: "def"}}, revisions)