Skip to content

Commit 73aa7f9

Browse files
richmahnGogs
authored andcommitted
Feature - Pagination for git tree API (go-gitea#5838)
* Feature - Pagination for git tree API * Handles case when page is negative * Does a for loop over the start and end rather than all entries * Removed redundent logic * Adds per_page as a query parameter * Adds DEFAULT_GIT_TREES_PER_PAGE for settings, ran make fmt * Fix typo in cheat-sheet en * Makes page start at 1, generated swagger * Use updates to SDK * Updates to use latest sdk * Updates swagger for tree api * Adds test for GetTreeBySHA * Updates per PR reviews * Updates per PR reviews * Remove file * Formatting * Fix to swagger file * Fix to swagger * Update v1_json.tmpl * Fix to swagger file
1 parent 467cdd3 commit 73aa7f9

File tree

9 files changed

+162
-29
lines changed

9 files changed

+162
-29
lines changed

Gopkg.lock

Lines changed: 10 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

custom/conf/app.ini.sample

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,10 @@ MIN_INTERVAL = 10m
610610
ENABLE_SWAGGER = true
611611
; Max number of items in a page
612612
MAX_RESPONSE_ITEMS = 50
613+
; Default paging number of api
614+
DEFAULT_PAGING_NUM = 30
615+
; Default and maximum number of items per page for git trees api
616+
DEFAULT_GIT_TREES_PER_PAGE = 1000
613617

614618
[i18n]
615619
LANGS = en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,uk-UA,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR

docs/content/doc/advanced/config-cheat-sheet.en-us.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,8 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
317317

318318
- `ENABLE_SWAGGER_ENDPOINT`: **true**: Enables /api/swagger, /api/v1/swagger etc. endpoints. True or false; default is true.
319319
- `MAX_RESPONSE_ITEMS`: **50**: Max number of items in a page.
320+
- `DEFAULT_PAGING_NUM`: **30**: Default paging number of api.
321+
- `DEFAULT_GIT_TREES_PER_PAGE`: **1000**: Default and maximum number of items per page for git trees api.
320322

321323
## i18n (`i18n`)
322324

docs/content/doc/advanced/config-cheat-sheet.zh-cn.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,14 @@ menu:
194194
- `PULL`: **300**: 内部仓库间拉取的超时时间,单位秒
195195
- `GC`: **60**: git仓库GC的超时时间,单位秒
196196

197-
## markup (`markup`)
197+
## API (`api`)
198+
199+
- `ENABLE_SWAGGER`: **true**: 是否启用swagger路由 /api/swagger, /api/v1/swagger etc. endpoints. True 或 false; 默认是 true.
200+
- `MAX_RESPONSE_ITEMS`: **50**: 一个页面最大的项目数。
201+
- `DEFAULT_PAGING_NUM`: **30**: API中默认分页条数。
202+
- `DEFAULT_GIT_TREES_PER_PAGE`: **1000**: GIT TREES API每页的默认和最大项数.
203+
204+
## Markup (`markup`)
198205

199206
外部渲染工具支持,你可以用你熟悉的文档渲染工具. 比如一下将新增一个名字为 `asciidoc` 的渲染工具which is followed `markup.` ini section. And there are some config items below.
200207

modules/setting/setting.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -549,11 +549,15 @@ var (
549549

550550
// API settings
551551
API = struct {
552-
EnableSwagger bool
553-
MaxResponseItems int
552+
EnableSwagger bool
553+
MaxResponseItems int
554+
DefaultPagingNum int
555+
DefaultGitTreesPerPage int
554556
}{
555-
EnableSwagger: true,
556-
MaxResponseItems: 50,
557+
EnableSwagger: true,
558+
MaxResponseItems: 50,
559+
DefaultPagingNum: 30,
560+
DefaultGitTreesPerPage: 1000,
557561
}
558562

559563
U2F = struct {

routers/api/v1/repo/tree.go

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,34 @@ func GetTree(ctx *context.APIContext) {
3737
// description: sha of the commit
3838
// type: string
3939
// required: true
40+
// - name: recursive
41+
// in: query
42+
// description: show all directories and files
43+
// required: false
44+
// type: boolean
45+
// - name: page
46+
// in: query
47+
// description: page number; the 'truncated' field in the response will be true if there are still more items after this page, false if the last page
48+
// required: false
49+
// type: integer
50+
// - name: per_page
51+
// in: query
52+
// description: number of items per page; default is 1000 or what is set in app.ini as DEFAULT_GIT_TREES_PER_PAGE
53+
// required: false
54+
// type: integer
4055
// responses:
4156
// "200":
4257
// "$ref": "#/responses/GitTreeResponse"
4358
sha := ctx.Params("sha")
4459
if len(sha) == 0 {
45-
ctx.Error(400, "sha not provided", nil)
60+
ctx.Error(400, "", "sha not provided")
4661
return
4762
}
4863
tree := GetTreeBySHA(ctx, sha)
4964
if tree != nil {
5065
ctx.JSON(200, tree)
5166
} else {
52-
ctx.Error(400, "sha invalid", nil)
67+
ctx.Error(400, "", "sha invalid")
5368
}
5469
}
5570

@@ -87,29 +102,44 @@ func GetTreeBySHA(ctx *context.APIContext, sha string) *gitea.GitTreeResponse {
87102
// 40 is the size of the sha1 hash in hexadecimal format.
88103
copyPos := len(treeURL) - 40
89104

90-
if len(entries) > 1000 {
91-
tree.Entries = make([]gitea.GitEntry, 1000)
105+
page := ctx.QueryInt("page")
106+
perPage := ctx.QueryInt("per_page")
107+
if perPage <= 0 || perPage > setting.API.DefaultGitTreesPerPage {
108+
perPage = setting.API.DefaultGitTreesPerPage
109+
}
110+
if page <= 0 {
111+
page = 1
112+
}
113+
tree.Page = page
114+
tree.TotalCount = len(entries)
115+
rangeStart := perPage * (page - 1)
116+
if rangeStart >= len(entries) {
117+
return tree
118+
}
119+
var rangeEnd int
120+
if len(entries) > perPage {
121+
tree.Truncated = true
122+
}
123+
if rangeStart+perPage < len(entries) {
124+
rangeEnd = rangeStart + perPage
92125
} else {
93-
tree.Entries = make([]gitea.GitEntry, len(entries))
126+
rangeEnd = len(entries)
94127
}
95-
for e := range entries {
96-
if e > 1000 {
97-
tree.Truncated = true
98-
break
99-
}
100-
101-
tree.Entries[e].Path = entries[e].Name()
102-
tree.Entries[e].Mode = fmt.Sprintf("%06x", entries[e].Mode())
103-
tree.Entries[e].Type = string(entries[e].Type)
104-
tree.Entries[e].Size = entries[e].Size()
105-
tree.Entries[e].SHA = entries[e].ID.String()
128+
tree.Entries = make([]gitea.GitEntry, rangeEnd-rangeStart)
129+
for e := rangeStart; e < rangeEnd; e++ {
130+
i := e - rangeStart
131+
tree.Entries[i].Path = entries[e].Name()
132+
tree.Entries[i].Mode = fmt.Sprintf("%06x", entries[e].Mode())
133+
tree.Entries[i].Type = string(entries[e].Type)
134+
tree.Entries[i].Size = entries[e].Size()
135+
tree.Entries[i].SHA = entries[e].ID.String()
106136

107137
if entries[e].IsDir() {
108138
copy(treeURL[copyPos:], entries[e].ID.String())
109-
tree.Entries[e].URL = string(treeURL[:])
139+
tree.Entries[i].URL = string(treeURL[:])
110140
} else {
111141
copy(blobURL[copyPos:], entries[e].ID.String())
112-
tree.Entries[e].URL = string(blobURL[:])
142+
tree.Entries[i].URL = string(blobURL[:])
113143
}
114144
}
115145
return tree

routers/api/v1/repo/tree_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2019 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package repo
6+
7+
import (
8+
"github.com/stretchr/testify/assert"
9+
"testing"
10+
11+
"code.gitea.io/gitea/models"
12+
"code.gitea.io/gitea/modules/context"
13+
"code.gitea.io/gitea/modules/test"
14+
"code.gitea.io/sdk/gitea"
15+
)
16+
17+
func TestGetTreeBySHA(t *testing.T) {
18+
models.PrepareTestEnv(t)
19+
sha := "master"
20+
ctx := test.MockContext(t, "user2/repo1")
21+
ctx.SetParams(":id", "1")
22+
ctx.SetParams(":sha", sha)
23+
test.LoadRepo(t, ctx, 1)
24+
test.LoadRepoCommit(t, ctx)
25+
test.LoadUser(t, ctx, 2)
26+
test.LoadGitRepo(t, ctx)
27+
28+
tree := GetTreeBySHA(&context.APIContext{Context: ctx, Org: nil}, ctx.Params("sha"))
29+
expectedTree := &gitea.GitTreeResponse{
30+
SHA: "65f1bf27bc3bf70f64657658635e66094edbcb4d",
31+
URL: "https://try.gitea.io/api/v1/repos/user2/repo1/git/trees/65f1bf27bc3bf70f64657658635e66094edbcb4d",
32+
Entries: []gitea.GitEntry{
33+
{
34+
Path: "README.md",
35+
Mode: "100644",
36+
Type: "blob",
37+
Size: 30,
38+
SHA: "4b4851ad51df6a7d9f25c979345979eaeb5b349f",
39+
URL: "https://try.gitea.io/api/v1/repos/user2/repo1/git/blobs/4b4851ad51df6a7d9f25c979345979eaeb5b349f",
40+
},
41+
},
42+
Truncated: false,
43+
Page: 1,
44+
TotalCount: 1,
45+
}
46+
47+
assert.EqualValues(t, tree, expectedTree)
48+
}

templates/swagger/v1_json.tmpl

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1694,6 +1694,24 @@
16941694
"name": "sha",
16951695
"in": "path",
16961696
"required": true
1697+
},
1698+
{
1699+
"type": "boolean",
1700+
"description": "show all directories and files",
1701+
"name": "recursive",
1702+
"in": "query"
1703+
},
1704+
{
1705+
"type": "integer",
1706+
"description": "page number; the 'truncated' field in the response will be true if there are still more items after this page, false if the last page",
1707+
"name": "page",
1708+
"in": "query"
1709+
},
1710+
{
1711+
"type": "integer",
1712+
"description": "number of items per page; default is 1000 or what is set in app.ini as DEFAULT_GIT_TREES_PER_PAGE",
1713+
"name": "per_page",
1714+
"in": "query"
16971715
}
16981716
],
16991717
"responses": {
@@ -7135,10 +7153,20 @@
71357153
"description": "GitTreeResponse returns a git tree",
71367154
"type": "object",
71377155
"properties": {
7156+
"page": {
7157+
"type": "integer",
7158+
"format": "int64",
7159+
"x-go-name": "Page"
7160+
},
71387161
"sha": {
71397162
"type": "string",
71407163
"x-go-name": "SHA"
71417164
},
7165+
"total_count": {
7166+
"type": "integer",
7167+
"format": "int64",
7168+
"x-go-name": "TotalCount"
7169+
},
71427170
"tree": {
71437171
"type": "array",
71447172
"items": {

vendor/code.gitea.io/sdk/gitea/repo_tree.go

Lines changed: 6 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)