add count|release|find
This commit is contained in:
parent
5bfe079500
commit
314ec710d6
|
@ -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
|
||||||
|
}
|
|
@ -65,11 +65,6 @@
|
||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"code.gitea.io/gitea/routers/api/v1/viewfile"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/auth"
|
"code.gitea.io/gitea/modules/auth"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"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/settings"
|
||||||
_ "code.gitea.io/gitea/routers/api/v1/swagger" // for swagger generation
|
_ "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/user"
|
||||||
|
"code.gitea.io/gitea/routers/api/v1/viewfile"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"gitea.com/macaron/binding"
|
"gitea.com/macaron/binding"
|
||||||
"gitea.com/macaron/macaron"
|
"gitea.com/macaron/macaron"
|
||||||
|
@ -123,8 +121,6 @@ func sudo() macaron.Handler {
|
||||||
|
|
||||||
func repoAssignment() macaron.Handler {
|
func repoAssignment() macaron.Handler {
|
||||||
return func(ctx *context.APIContext) {
|
return func(ctx *context.APIContext) {
|
||||||
start:=time.Now()
|
|
||||||
log.Info("****repoAssignment enter:")
|
|
||||||
userName := ctx.Params(":username")
|
userName := ctx.Params(":username")
|
||||||
repoName := ctx.Params(":reponame")
|
repoName := ctx.Params(":reponame")
|
||||||
|
|
||||||
|
@ -180,7 +176,6 @@ func repoAssignment() macaron.Handler {
|
||||||
ctx.NotFound()
|
ctx.NotFound()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Info("*****repoAssignment leave:%v",time.Now().Sub(start))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -675,7 +670,19 @@ func RegisterRoutes(m *macaron.Macaron) {
|
||||||
|
|
||||||
// alter on 2021/01/15
|
// alter on 2021/01/15
|
||||||
m.Get("", viewfile.Readme) // reqRepoReader(models.UnitTypeCode),
|
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).
|
m.Combo("").Get(reqAnyRepoReader(), repo.Get).
|
||||||
Delete(reqToken(), reqOwner(), repo.Delete).
|
Delete(reqToken(), reqOwner(), repo.Delete).
|
||||||
Patch(reqToken(), reqAdmin(), bind(api.EditRepoOption{}), context.RepoRef(), repo.Edit)
|
Patch(reqToken(), reqAdmin(), bind(api.EditRepoOption{}), context.RepoRef(), repo.Edit)
|
||||||
|
|
|
@ -2,7 +2,11 @@ package viewfile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/repofiles"
|
||||||
|
repo_module "code.gitea.io/gitea/modules/repository"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
gotemplate "html/template"
|
gotemplate "html/template"
|
||||||
|
@ -12,8 +16,6 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"code.gitea.io/gitea/models"
|
|
||||||
"code.gitea.io/gitea/modules/base"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/charset"
|
"code.gitea.io/gitea/modules/charset"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
|
@ -22,8 +24,6 @@ import (
|
||||||
"code.gitea.io/gitea/modules/markup"
|
"code.gitea.io/gitea/modules/markup"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"gitea.com/macaron/macaron"
|
"gitea.com/macaron/macaron"
|
||||||
|
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Map2DTO(ctx *context.APIContext) (dto *ReadmeDTO) {
|
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 repository’s 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) {
|
func Readme(ctx *context.APIContext) {
|
||||||
// swagger:operation GET /repos/{owner}/{repo}/readme repository readme
|
// 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
|
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 {
|
func IsReadmeFileExt(name string, ext ...string) bool {
|
||||||
name = strings.ToLower(name)
|
name = strings.ToLower(name)
|
||||||
if len(ext) > 0 {
|
if len(ext) > 0 {
|
||||||
|
|
Loading…
Reference in New Issue