add count|release|find

This commit is contained in:
hcxm 2021-01-22 14:24:17 +08:00
parent 5bfe079500
commit 314ec710d6
3 changed files with 344 additions and 12 deletions

29
models/release_ext.go Normal file
View File

@ -0,0 +1,29 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Copyright 2019 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 models
import "xorm.io/builder"
// GetLatestReleaseByRepoID returns the latest release for a repository
func GetLatestReleaseByRepoIDExt(repoID int64) (*Release, error) {
cond := builder.NewCond().
And(builder.Eq{"repo_id": repoID}).
And(builder.Eq{"is_draft": false}).
And(builder.Eq{"is_prerelease": false})
rel := new(Release)
has, err := x.
Desc("created_unix", "id").
Where(cond).
Get(rel)
if err != nil {
return nil, err
} else if !has {
return nil, ErrReleaseNotExist{0, "latest"}
}
return rel, nil
}

View File

@ -65,11 +65,6 @@
package v1
import (
"code.gitea.io/gitea/routers/api/v1/viewfile"
"net/http"
"strings"
"time"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/context"
@ -84,6 +79,9 @@ import (
"code.gitea.io/gitea/routers/api/v1/settings"
_ "code.gitea.io/gitea/routers/api/v1/swagger" // for swagger generation
"code.gitea.io/gitea/routers/api/v1/user"
"code.gitea.io/gitea/routers/api/v1/viewfile"
"net/http"
"strings"
"gitea.com/macaron/binding"
"gitea.com/macaron/macaron"
@ -123,8 +121,6 @@ func sudo() macaron.Handler {
func repoAssignment() macaron.Handler {
return func(ctx *context.APIContext) {
start:=time.Now()
log.Info("****repoAssignment enter:")
userName := ctx.Params(":username")
repoName := ctx.Params(":reponame")
@ -180,7 +176,6 @@ func repoAssignment() macaron.Handler {
ctx.NotFound()
return
}
log.Info("*****repoAssignment leave:%v",time.Now().Sub(start))
}
}
@ -675,7 +670,19 @@ func RegisterRoutes(m *macaron.Macaron) {
// alter on 2021/01/15
m.Get("", viewfile.Readme) // reqRepoReader(models.UnitTypeCode),
},reqToken())
m.Group("/count", func() {
m.Get("", viewfile.CommitCount)
})
m.Group("/releases", func() {
m.Get("/latest", viewfile.LatestRelease)
})
//
m.Group("/find", func() {
m.Get("", viewfile.FindFiles) //文件搜索 to do;
})
m.Combo("").Get(reqAnyRepoReader(), repo.Get).
Delete(reqToken(), reqOwner(), repo.Delete).
Patch(reqToken(), reqAdmin(), bind(api.EditRepoOption{}), context.RepoRef(), repo.Edit)

View File

@ -2,7 +2,11 @@ package viewfile
import (
"bytes"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/repofiles"
repo_module "code.gitea.io/gitea/modules/repository"
"encoding/base64"
"fmt"
gotemplate "html/template"
@ -12,8 +16,6 @@ import (
"path"
"strconv"
"strings"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/charset"
"code.gitea.io/gitea/modules/context"
@ -22,8 +24,6 @@ import (
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/setting"
"gitea.com/macaron/macaron"
)
func Map2DTO(ctx *context.APIContext) (dto *ReadmeDTO) {
@ -224,6 +224,165 @@ func GetRefType() macaron.Handler {
}
func CommitCount(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/count repository Count
// ---
// summary: Get commit quantity by branch
// 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
// - name: ref
// in: query
// description: "The name of the commit/branch/tag. Default the repositorys default branch (usually master)"
// type: string
// required: false
// responses:
// "200":
// "$ref": "#/responses/"
// "404":
// "$ref": "#/responses/notFound"
ref := ctx.QueryTrim("ref")
if ref == "" {
ref = ctx.Params(":ref")
if ref == "" {
ref = ctx.Repo.Repository.DefaultBranch
}
}
log.Info("********CommitCount:ref:%s", ref)
var err error
if ctx.Repo.GitRepo == nil {
fmt.Println("*****ctx.Repo.GitRepo is nil ")
repoPath := models.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)
ctx.Repo.GitRepo, err = git.OpenRepository(repoPath)
if err != nil {
ctx.ServerError("RepoRef Invalid repo "+repoPath, err)
return
}
// We opened it, we should close it
defer func() {
// If it's been set to nil then assume someone else has closed it.
if ctx.Repo.GitRepo != nil {
ctx.Repo.GitRepo.Close()
}
}()
}
// Get the commit object for the ref
commit, err := ctx.Repo.GitRepo.GetCommit(ref)
if err != nil || commit==nil{
ctx.Error(http.StatusInternalServerError,"ctx.Repo.GitRepo.GetCommit", err)
return
}
//log.Info("********GetCommit:%v",commit)
ctx.Repo.Commit=commit
CommitCount,err:=ctx.Repo.Commit.CommitsCount()
if err !=nil {
ctx.Error(http.StatusInternalServerError,"ctx.Repo.Commit.CommitsCount", err)
return
}
opts := models.FindReleasesOptions{
ListOptions: models.ListOptions{
Page: 1,
PageSize: 1000,
},
IncludeDrafts: true,
IncludeTags: true,
}
fmt.Println("*****************ctx.Repo.Repository.ID:",ctx.Repo.Repository.ID)
ReleaseCount, err := models.GetReleaseCountByRepoID(ctx.Repo.Repository.ID, opts)
if err != nil {
ctx.ServerError("GetReleaseCountByRepoID", err)
return
}
branches, err := repo_module.GetBranches(ctx.Repo.Repository)
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetBranches", err)
return
}
tags,err:=ctx.Repo.GitRepo.GetTags()
if err != nil {
ctx.Error(http.StatusInternalServerError, "ctx.Repo.GitRepo.GetTags", err)
return
}
dto:=&CountDTO{}
dto.Branch.CommitCount=CommitCount
dto.Branch.BranchName=ref
dto.BranchCount=int64(len(branches))
dto.TagCount=int64(len(tags))
dto.ReleaseCount=ReleaseCount
ctx.JSON(http.StatusOK, dto)
}
type CountDTO struct {
Branch struct{
CommitCount int64 `json:"commit_count"`
BranchName string `json:"branch_name"`
} `json:"branch"`
ReleaseCount int64 `json:"release_count"`
TagCount int64 `json:"tag_count"`
BranchCount int64 `json:"branch_count"`
}
// LatestRelease redirects to the latest release
func LatestRelease(ctx *context.APIContext) {
var err error
if ctx.Repo.GitRepo == nil {
fmt.Println("*****ctx.Repo.GitRepo is nil ")
repoPath := models.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)
ctx.Repo.GitRepo, err = git.OpenRepository(repoPath)
if err != nil {
ctx.ServerError("RepoRef Invalid repo "+repoPath, err)
return
}
// We opened it, we should close it
defer func() {
// If it's been set to nil then assume someone else has closed it.
if ctx.Repo.GitRepo != nil {
ctx.Repo.GitRepo.Close()
}
}()
}
release, err := models.GetLatestReleaseByRepoIDExt(ctx.Repo.Repository.ID)
fmt.Println("****************ctx.Repo.Repository.ID:",ctx.Repo.Repository.ID," ",release," ",err)
if err != nil {
if models.IsErrReleaseNotExist(err) {
ctx.NotFound("LatestRelease", err)
return
}
ctx.ServerError("GetLatestReleaseByRepoID", err)
return
}
if err := release.LoadAttributes(); err != nil {
ctx.ServerError("LoadAttributes", err)
return
}
ctx.JSON(http.StatusOK, release)
}
func Readme(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/readme repository readme
// ---
@ -814,6 +973,143 @@ func getReadmeFileFromPathExt(ctx *context.APIContext, treePath, ref string) (*n
return readmeFile, nil
}
// TO DO
func FindFiles(ctx *context.APIContext) {
treePath := ctx.Repo.TreePath
ref:= ctx.QueryTrim("ref")
if ref == "" {
ref = ctx.Repo.Repository.DefaultBranch
}
fmt.Println("***ref:",ref)
keyword:= ctx.QueryTrim("keyword")
if keyword == "" {
keyword="README" //test
}
FindList,err:=FindFileFromPathExt(ctx,treePath,ref,keyword)
if err !=nil {
ctx.NotFound("FindFiles", err)
return
}
ctx.JSON(http.StatusOK,FindList)
}
// TO DO
func FindFileFromPathExt(ctx *context.APIContext, treePath, ref, key string) (fileList []*SearchFileItem, err error) {
if ctx.Repo.GitRepo == nil {
repoPath := models.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)
ctx.Repo.GitRepo, err = git.OpenRepository(repoPath)
if err != nil {
ctx.ServerError("RepoRef Invalid repo "+repoPath, err)
return nil,err
}
// We opened it, we should close it
defer func() {
// If it's been set to nil then assume someone else has closed it.
if ctx.Repo.GitRepo != nil {
ctx.Repo.GitRepo.Close()
}
}()
}
// Get the commit object for the ref
commit, err := ctx.Repo.GitRepo.GetCommit(ref)
if err != nil {
return nil, err
}
tree, err := commit.SubTree(treePath)
if err != nil {
return nil, err
}
entries, err := tree.ListEntries()
if err != nil {
return nil, err
}
for _, entry := range entries {
if entry.IsDir() {
continue
}
if strings.Contains(strings.ToLower(entry.Name()),strings.ToLower( key)) || key=="" {
name := entry.Name()
isSymlink := entry.IsLink()
target := entry
_=target
if isSymlink {
target, err = entry.FollowLinks()
if err != nil && !git.IsErrBadLink(err) {
return nil, err
}
}
treePath=name
selfURL, err := url.Parse(fmt.Sprintf("%s/contents/%s?ref=%s", ctx.Repo.Repository.APIURL(), treePath, ref))
if err != nil {
return nil, err
}
selfURLString := selfURL.String()
refType := ctx.Repo.GitRepo.GetRefType(ref)
if refType == "invalid" {
return nil, fmt.Errorf("no commit found for the ref [ref: %s]", ref)
}
htmlURL, err := url.Parse(fmt.Sprintf("%s/src/%s/%s/%s", ctx.Repo.Repository.HTMLURL(), refType, ref, treePath))
if err != nil {
return nil, err
}
htmlURLString := htmlURL.String()
Item := &SearchFileItem{
Name:name,
Path:treePath,
SHA:entry.ID.String(),
Type:entry.Type(),
Size:entry.Size(),
URL:&selfURLString,
HTMLURL:&htmlURLString,
}
// Now populate the rest of the ContentsResponse based on entry type
if entry.IsRegular() || entry.IsExecutable() {
Item.Type = string(repofiles.ContentTypeRegular)
} else if entry.IsDir() {
Item.Type = string(repofiles.ContentTypeDir)
} else if entry.IsLink() {
Item.Type = string(repofiles.ContentTypeLink)
} else if entry.IsSubModule() {
Item.Type = string(repofiles.ContentTypeSubmodule)
}
fileList=append(fileList,Item)
}
}
return
}
type SearchFileItem struct {
Name string `json:"name"`
Path string `json:"path"`
SHA string `json:"sha"`
// `type` will be `file`, `dir`, `symlink`, or `submodule`
Type string `json:"type"`
Size int64 `json:"size"`
URL *string `json:"url"`
HTMLURL *string `json:"html_url"`
// GitURL *string `json:"git_url"`
// DownloadURL *string `json:"download_url"`
// // `submodule_git_url` is populated when `type` is `submodule`, otherwise null
// SubmoduleGitURL *string `json:"submodule_git_url"`
// Links *api.FileLinksResponse `json:"_links"`
}
func IsReadmeFileExt(name string, ext ...string) bool {
name = strings.ToLower(name)
if len(ext) > 0 {