mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	Add language statistics API endpoint (#11737)
* Add language statistics API * Add tests
This commit is contained in:
		
							
								
								
									
										46
									
								
								integrations/api_repo_languages_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								integrations/api_repo_languages_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| // Copyright 2020 The Gitea Authors. All rights reserved. | ||||
| // Use of this source code is governed by a MIT-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package integrations | ||||
|  | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func TestRepoLanguages(t *testing.T) { | ||||
| 	onGiteaRun(t, func(t *testing.T, u *url.URL) { | ||||
| 		session := loginUser(t, "user2") | ||||
|  | ||||
| 		// Request editor page | ||||
| 		req := NewRequest(t, "GET", "/user2/repo1/_new/master/") | ||||
| 		resp := session.MakeRequest(t, req, http.StatusOK) | ||||
|  | ||||
| 		doc := NewHTMLParser(t, resp.Body) | ||||
| 		lastCommit := doc.GetInputValueByName("last_commit") | ||||
| 		assert.NotEmpty(t, lastCommit) | ||||
|  | ||||
| 		// Save new file to master branch | ||||
| 		req = NewRequestWithValues(t, "POST", "/user2/repo1/_new/master/", map[string]string{ | ||||
| 			"_csrf":         doc.GetCSRF(), | ||||
| 			"last_commit":   lastCommit, | ||||
| 			"tree_path":     "test.go", | ||||
| 			"content":       "package main", | ||||
| 			"commit_choice": "direct", | ||||
| 		}) | ||||
| 		session.MakeRequest(t, req, http.StatusFound) | ||||
|  | ||||
| 		// Save new file to master branch | ||||
| 		req = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/languages") | ||||
| 		resp = session.MakeRequest(t, req, http.StatusOK) | ||||
|  | ||||
| 		var languages map[string]int64 | ||||
| 		DecodeJSON(t, resp, &languages) | ||||
|  | ||||
| 		assert.InDeltaMapValues(t, map[string]int64{"Go": 12}, languages, 0) | ||||
| 	}) | ||||
| } | ||||
| @@ -855,6 +855,7 @@ func RegisterRoutes(m *macaron.Macaron) { | ||||
| 							Delete(reqToken(), repo.DeleteTopic) | ||||
| 					}, reqAdmin()) | ||||
| 				}, reqAnyRepoReader()) | ||||
| 				m.Get("/languages", reqRepoReader(models.UnitTypeCode), repo.GetLanguages) | ||||
| 			}, repoAssignment()) | ||||
| 		}) | ||||
|  | ||||
|   | ||||
							
								
								
									
										84
									
								
								routers/api/v1/repo/language.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								routers/api/v1/repo/language.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| // Copyright 2020 The Gitea Authors. All rights reserved. | ||||
| // Use of this source code is governed by a MIT-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package repo | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"net/http" | ||||
| 	"strconv" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models" | ||||
| 	"code.gitea.io/gitea/modules/context" | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| ) | ||||
|  | ||||
| type languageResponse []*models.LanguageStat | ||||
|  | ||||
| func (l languageResponse) MarshalJSON() ([]byte, error) { | ||||
| 	var buf bytes.Buffer | ||||
| 	if _, err := buf.WriteString("{"); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	for i, lang := range l { | ||||
| 		if i > 0 { | ||||
| 			if _, err := buf.WriteString(","); err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 		} | ||||
| 		if _, err := buf.WriteString(strconv.Quote(lang.Language)); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		if _, err := buf.WriteString(":"); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		if _, err := buf.WriteString(strconv.FormatInt(lang.Size, 10)); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	if _, err := buf.WriteString("}"); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return buf.Bytes(), nil | ||||
| } | ||||
|  | ||||
| // GetLanguages returns languages and number of bytes of code written | ||||
| func GetLanguages(ctx *context.APIContext) { | ||||
| 	// swagger:operation GET /repos/{owner}/{repo}/languages repository repoGetLanguages | ||||
| 	// --- | ||||
| 	// summary: Get languages and number of bytes of code written | ||||
| 	// produces: | ||||
| 	//   - application/json | ||||
| 	// parameters: | ||||
| 	// - name: owner | ||||
| 	//   in: path | ||||
| 	//   description: owner of the repo | ||||
| 	//   type: string | ||||
| 	//   required: true | ||||
| 	// - name: repo | ||||
| 	//   in: path | ||||
| 	//   description: name of the repo | ||||
| 	//   type: string | ||||
| 	//   required: true | ||||
| 	// responses: | ||||
| 	//   "404": | ||||
| 	//     "$ref": "#/responses/notFound" | ||||
| 	//   "200": | ||||
| 	//     "$ref": "#/responses/LanguageStatistics" | ||||
|  | ||||
| 	langs, err := ctx.Repo.Repository.GetLanguageStats() | ||||
| 	if err != nil { | ||||
| 		log.Error("GetLanguageStats failed: %v", err) | ||||
| 		ctx.InternalServerError(err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	resp := make(languageResponse, len(langs)) | ||||
| 	for i, v := range langs { | ||||
| 		resp[i] = v | ||||
| 	} | ||||
|  | ||||
| 	ctx.JSON(http.StatusOK, resp) | ||||
| } | ||||
| @@ -302,3 +302,10 @@ type swaggerTopicNames struct { | ||||
| 	// in: body | ||||
| 	Body api.TopicName `json:"body"` | ||||
| } | ||||
|  | ||||
| // LanguageStatistics | ||||
| // swagger:response LanguageStatistics | ||||
| type swaggerLanguageStatistics struct { | ||||
| 	// in: body | ||||
| 	Body map[string]int64 `json:"body"` | ||||
| } | ||||
|   | ||||
| @@ -6049,6 +6049,42 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "/repos/{owner}/{repo}/languages": { | ||||
|       "get": { | ||||
|         "produces": [ | ||||
|           "application/json" | ||||
|         ], | ||||
|         "tags": [ | ||||
|           "repository" | ||||
|         ], | ||||
|         "summary": "Get languages and number of bytes of code written", | ||||
|         "operationId": "repoGetLanguages", | ||||
|         "parameters": [ | ||||
|           { | ||||
|             "type": "string", | ||||
|             "description": "owner of the repo", | ||||
|             "name": "owner", | ||||
|             "in": "path", | ||||
|             "required": true | ||||
|           }, | ||||
|           { | ||||
|             "type": "string", | ||||
|             "description": "name of the repo", | ||||
|             "name": "repo", | ||||
|             "in": "path", | ||||
|             "required": true | ||||
|           } | ||||
|         ], | ||||
|         "responses": { | ||||
|           "200": { | ||||
|             "$ref": "#/responses/LanguageStatistics" | ||||
|           }, | ||||
|           "404": { | ||||
|             "$ref": "#/responses/notFound" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "/repos/{owner}/{repo}/milestones": { | ||||
|       "get": { | ||||
|         "produces": [ | ||||
| @@ -14917,6 +14953,16 @@ | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "LanguageStatistics": { | ||||
|       "description": "LanguageStatistics", | ||||
|       "schema": { | ||||
|         "type": "object", | ||||
|         "additionalProperties": { | ||||
|           "type": "integer", | ||||
|           "format": "int64" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "MarkdownRender": { | ||||
|       "description": "MarkdownRender is a rendered markdown document", | ||||
|       "schema": { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user