Compare commits

..

78 Commits

Author SHA1 Message Date
jasder 3e9b0dc1c5 Merge pull request '更新到正式环境' (#29) from develop into master 2021-10-09 14:44:59 +08:00
yystopf de0f7764c7 fix merge from hh_file_commits 2021-10-08 14:26:21 +08:00
yystopf 15882844c6 add: tags list page info 2021-09-30 16:09:11 +08:00
yystopf d78a760be7 Merge pull request '返回commit 的branch' (#28) from wonderful/gitea-1120-rc1:develop_m into develop 2021-09-29 15:29:48 +08:00
hang 06dd55c49f add commit's branch 2021-09-29 15:22:06 +08:00
yystopf 9ee3486d44 add: commit detail branch 2021-09-29 10:31:09 +08:00
yystopf 52232e2431 发行版增加提交id字段输出 2021-09-27 16:54:42 +08:00
yystopf c37047eeaf add: release list sha 2021-09-27 16:51:08 +08:00
jasder bfbd16b7df Merge pull request '项目标签增加提交和打标签的信息' (#26) from yystopf/gitea-1120-rc1:hh_tag_addition into develop 2021-09-24 17:54:20 +08:00
yystopf b82b5bf80b add: add tag message 2021-09-24 17:49:54 +08:00
yystopf 796c78996b add: commits by file 2021-09-23 16:36:12 +08:00
jasder 705694ff88 Merge pull request '对tags接口修改' (#25) from wonderful/gitea-1120-rc1:develop_w into develop 2021-09-23 15:56:43 +08:00
hang 6270454d59 fix:tags 2021-09-23 15:48:36 +08:00
jasder 04f3e061cb Merge pull request '添加tags/releases接口' (#24) from wonderful/gitea-1120-rc1:develop_w into develop 2021-09-23 10:48:38 +08:00
hang 8f47d8df52 add:tags/releases 2021-09-23 10:36:59 +08:00
jasder dfc39ebda0 Merge pull request '添加 reamde/{dir}接口' (#23) from wonderful/gitea-1120-rc1:develop_w into develop 2021-09-23 10:30:42 +08:00
hang ad3ccfb22f add:readme dir 2021-09-23 10:25:02 +08:00
jasder 4e0a133712 Merge pull request '仓库获取文件添加分支、commit、tag参数' (#20) from yystopf/gitea-1120-rc1:hh_raw_delay into develop 2021-09-10 11:37:47 +08:00
yystopf 9f80111504 fix: get file need ref to select 2021-09-10 11:26:49 +08:00
jasder 20c13e8352 Merge pull request '添加branches分组接口' (#19) from wonderful/gitea-1120-rc1:develop into develop 2021-09-07 14:04:11 +08:00
wonderful 71df4fdfa1 add:grouping the branches and sort by time 2021-09-07 12:06:31 +08:00
jasder 20e2cb271e Merge pull request '根据时间排序commits并分组' (#18) from wonderful/gitea-1120-rc1:develop into develop 2021-09-07 12:00:56 +08:00
wonderful fdfe572500 add:sort the branches by time 2021-09-07 11:30:02 +08:00
yystopf 86fb4bb8d8 fix: edit wiki name not exsit error 2021-08-20 14:56:49 +08:00
yystopf 0c897c660f fix: create or update exsit name error 2021-08-19 22:20:48 +08:00
yystopf 2b54b5c39a wiki相关功能以及接口 2021-08-19 18:05:04 +08:00
yystopf 9d53ff793b fix:merge from wmh_develop 2021-08-19 18:02:04 +08:00
wonderful 3072fc7e4e fix:first wikies 2021-08-19 17:44:25 +08:00
wonderful b228c9f602 fix: 2021-08-19 14:38:07 +08:00
yystopf f13f296790 add: get first and last commit by path 2021-08-19 14:25:37 +08:00
wonderful 64ef5a1567 wikies 2021-08-18 18:53:11 +08:00
wonderful b8599a9fa2 fix 2021-08-18 13:29:44 +08:00
wonderful fd05b7938e fix 2021-08-18 13:16:28 +08:00
wonderful 89eb38f44c fix:wikit 2021-08-18 12:57:31 +08:00
wonderful 5decf76ec3 fix:wiki 2021-08-18 09:58:50 +08:00
wonderful 925a7b18cb fix:wiki 2021-08-18 08:11:25 +08:00
wonderful 6f2fdf1159 fix:wiki 2021-08-17 23:49:14 +08:00
wonderful 98122e3cb6 fix:wiki 2021-08-17 18:32:17 +08:00
wonderful fd02b7beb9 fix:wiki 2021-08-17 17:50:39 +08:00
wonderful 10e2b49064 fix:wikies 2021-08-17 14:45:45 +08:00
wonderful 554fd29ebb fix:wikies 2021-08-17 11:41:26 +08:00
wonderful e6c3986962 fix:wiki 2021-08-16 17:43:59 +08:00
wonderful ad679b575e fix:wiki 2021-08-16 16:12:20 +08:00
wonderful e26a306415 fix:delete wiki 2021-08-16 15:14:55 +08:00
wonderful c2392616b5 fix:filename 2021-08-16 13:49:18 +08:00
wonderful 0e9fd60786 fix:wiki 2021-08-15 17:38:12 +08:00
wonderful 7e486f8038 fix:wiki content 2021-08-15 13:58:27 +08:00
wonderful 3e792b0c0f add:WContent 2021-08-13 17:39:58 +08:00
wonderful 6b34e16a7c fix:add htmlcontent 2021-08-13 17:14:18 +08:00
wonderful d3f8e67e57 fix:wikies 2021-08-13 13:57:02 +08:00
wonderful 2d5a3202bd fix: add wiki_clone_link 2021-08-12 18:18:16 +08:00
wonderful 7a98e1ad9a add wikies repository 2021-08-12 09:51:29 +08:00
yystopf 94d7873f11 Merge branch 'develop' of https://git.trustie.net/jasder/gitea-1120-rc1 into develop 2021-08-09 15:05:34 +08:00
yystopf a22ccad9f9 repository wikies modules 2021-08-09 15:05:15 +08:00
wonderful 23f2dc9c23 fix modules/wikies/wiki.go /api/v1/repo/wiki.go 2021-08-09 14:38:48 +08:00
yystopf d9495f6822 fix: api use restful and back data example 2021-08-06 16:58:04 +08:00
yystopf 30537e038a Merge branch 'develop' of https://git.trustie.net/jasder/gitea-1120-rc1 into develop 2021-08-06 09:53:05 +08:00
wonderful ca7dad0ebc fix wiki.go api.go content.go 2021-08-05 17:35:03 +08:00
wonderful 8033fc6a45 fix repo.go 2021-08-05 17:20:53 +08:00
wonderful 757a3816f7 new wiki.go content.go, fix api.go 2021-08-05 16:53:03 +08:00
wonderful dbd0b2661e add wiki.go content.go fix, api.go repo.go 2021-08-05 16:35:04 +08:00
viletyy 611e58f5ae Merge branch 'hh_develop' into develop 2021-08-05 16:28:52 +08:00
viletyy 3b5dff2e23 Merge branch 'wmh_develop' of https://git.trustie.net/jasder/gitea-1120-rc1 into wmh_develop 2021-07-28 21:46:29 +08:00
wonderful aa27fd6457 HookTasks list 2021-07-28 19:32:33 +08:00
wonderful ac62431593 HookTasks list 2021-07-28 18:42:39 +08:00
viletyy 2a73cddad1 Merge branch 'hh_develop' into develop 2021-07-28 18:17:33 +08:00
viletyy fa35eaab21 fix 2021-07-28 18:17:13 +08:00
viletyy 8e64f038ac fix: webhook change secret\branch_filter\eventtype 2021-07-28 17:31:39 +08:00
yystopf 1014b45ec1 webhook的http_method和branch_filter字段返回 2021-07-27 18:34:45 +08:00
viletyy 6050736a0b fix: remove http_method to config 2021-07-27 18:19:07 +08:00
viletyy 8609403fe9 fix: remove repo edit from file 2021-07-27 17:31:43 +08:00
yystopf 747b6205e2 修改webhook API的返回参数
- http_method
- branch_filter
2021-07-27 17:29:33 +08:00
wonderful 9c568c2a59 fix: utils/hook webhook 2021-07-27 17:12:38 +08:00
viletyy 6dd4ff2c87 Merge branch 'develop' of https://git.trustie.net/jasder/gitea-1120-rc1 into develop 2021-07-09 11:08:23 +08:00
viletyy 4674286786 fix: repo submodule is nil 2021-07-09 11:08:17 +08:00
yystopf a3f760ac2d API:用户贡献度支持时间筛选 2021-06-04 18:56:58 +08:00
vilet.yy ff366f6c6a fix: include timestamp critical value 2021-06-02 15:05:24 +08:00
vilet.yy b8fd0c3f98 add: user headmap timestamp range 2021-05-26 14:14:09 +08:00
38 changed files with 3062 additions and 385 deletions

View File

@ -96,6 +96,7 @@ func (r *Release) APIFormat() *api.Release {
TagName: r.TagName, TagName: r.TagName,
Target: r.Target, Target: r.Target,
Title: r.Title, Title: r.Title,
Sha1: r.Sha1,
Note: r.Note, Note: r.Note,
URL: r.APIURL(), URL: r.APIURL(),
HTMLURL: r.HTMLURL(), HTMLURL: r.HTMLURL(),

View File

@ -994,7 +994,9 @@ func (repo *Repository) cloneLink(isWiki bool) *CloneLink {
func (repo *Repository) CloneLink() (cl *CloneLink) { func (repo *Repository) CloneLink() (cl *CloneLink) {
return repo.cloneLink(false) return repo.cloneLink(false)
} }
func (repo *Repository) CloneWikiLink() (cl *CloneLink) {
return repo.cloneLink(true)
}
// CheckCreateRepository check if could created a repository // CheckCreateRepository check if could created a repository
func CheckCreateRepository(doer, u *User, name string) error { func CheckCreateRepository(doer, u *User, name string) error {
if !doer.CanCreateRepo() { if !doer.CanCreateRepo() {

View File

@ -0,0 +1,18 @@
package models
import "code.gitea.io/gitea/modules/timeutil"
type TimestampOptions struct {
Start timeutil.TimeStamp
End timeutil.TimeStamp
}
func (opts *TimestampOptions) setDefaultValues() {
if opts.Start <= 0 {
opts.Start = timeutil.TimeStampNow() - 365*24*60*60
}
if opts.End <= 0 {
opts.End = timeutil.TimeStampNow()
}
}

View File

@ -56,3 +56,42 @@ func GetUserHeatmapDataByUser(user *User) ([]*UserHeatmapData, error) {
return hdata, err return hdata, err
} }
func GetUserHeatMapDataByUserWithTimeStamp(user *User, opts TimestampOptions) ([]*UserHeatmapData, error) {
opts.setDefaultValues()
hdata := make([]*UserHeatmapData, 0)
if user.KeepActivityPrivate {
return hdata, nil
}
var groupBy string
var groupByName = "timestamp"
switch {
case setting.Database.UseSQLite3:
groupBy = "strftime('%s', strftime('%Y-%m-%d', created_unix, 'unixepoch'))"
case setting.Database.UseMySQL:
groupBy = "UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(created_unix)))"
case setting.Database.UsePostgreSQL:
groupBy = "extract(epoch from data_trunc('day', to_timestamp(created_unix)))"
case setting.Database.UseMSSQL:
groupBy = "datediff(SECOND, '19700101', dateadd(DAY, 0, datediff(day, 0, dateadd(s, created_unix, '19700101'))))"
groupByName = groupBy
}
sess := x.Select(groupBy+" AS timestamp, count(user_id) as contributions").
Table("action").
Where("user_id = ?", user.ID).
And(groupBy+" >= ?", opts.Start).
And(groupBy+" <= ?", opts.End)
if user.Type == UserTypeIndividual {
sess = sess.And("act_user_id = ?", user.ID)
}
err := sess.GroupBy(groupByName).
OrderBy("timestamp").
Find(&hdata)
return hdata, err
}

View File

@ -55,6 +55,13 @@ func IsValidHookContentType(name string) bool {
return ok return ok
} }
func IsValidHookHttpMethod(name string) bool {
if name == "POST" || name == "GET" {
return true
}
return false
}
// HookEvents is a set of web hook events // HookEvents is a set of web hook events
type HookEvents struct { type HookEvents struct {
Create bool `json:"create"` Create bool `json:"create"`
@ -115,6 +122,7 @@ type Webhook struct {
HookTaskType HookTaskType HookTaskType HookTaskType
Meta string `xorm:"TEXT"` // store hook-specific attributes Meta string `xorm:"TEXT"` // store hook-specific attributes
LastStatus HookStatus // Last delivery status LastStatus HookStatus // Last delivery status
BranchFilter string `xorm:"TEXT"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
@ -748,6 +756,18 @@ func (t *HookTask) simpleMarshalJSON(v interface{}) string {
return string(p) return string(p)
} }
func GetHookTasksByRepoIDAndHookID(repoID int64, hookID int64, listOptions ListOptions) ([]*HookTask, error) {
if listOptions.Page == 0 {
hookTasks := make([]*HookTask, 0, 5)
return hookTasks, x.Find(&hookTasks, &HookTask{RepoID: repoID, HookID: hookID})
}
sess := listOptions.getPaginatedSession()
hookTasks := make([]*HookTask, 0, listOptions.PageSize)
return hookTasks, sess.Find(&hookTasks, &HookTask{RepoID: repoID, HookID: hookID})
}
// HookTasks returns a list of hook tasks by given conditions. // HookTasks returns a list of hook tasks by given conditions.
func HookTasks(hookID int64, page int) ([]*HookTask, error) { func HookTasks(hookID int64, page int) ([]*HookTask, error) {
tasks := make([]*HookTask, 0, setting.Webhook.PagingNum) tasks := make([]*HookTask, 0, setting.Webhook.PagingNum)

View File

@ -234,7 +234,7 @@ func ReferencesGitRepo(allowEmpty bool) macaron.Handler {
// NotFound handles 404s for APIContext // NotFound handles 404s for APIContext
// String will replace message, errors will be added to a slice // String will replace message, errors will be added to a slice
func (ctx *APIContext) NotFound(objs ...interface{}) { func (ctx *APIContext) NotFound(objs ...interface{}) {
var message = "Not Found" var message = "Not Found (ownerName,repo etc...)"
var errors []string var errors []string
for _, obj := range objs { for _, obj := range objs {
// Ignore nil // Ignore nil
@ -255,3 +255,94 @@ func (ctx *APIContext) NotFound(objs ...interface{}) {
"errors": errors, "errors": errors,
}) })
} }
func (ctx *APIContext) FileNameError(objs ...interface{}){
var message = "FileName too long"
var errors []string
for _, obj := range objs {
// Ignore nil
if obj == nil {
continue
}
if err, ok := obj.(error); ok {
errors = append(errors, err.Error())
} else {
message = obj.(string)
}
}
ctx.JSON(500, map[string]interface{}{
"message": message,
"documentation_url": setting.API.SwaggerURL,
"errors": errors,
})
}
func (ctx *APIContext) SameFileNameError(objs ...interface{}){
var message = "Same name exists"
var errors []string
for _, obj := range objs {
// Ignore nil
if obj == nil {
continue
}
if err, ok := obj.(error); ok {
errors = append(errors, err.Error())
} else {
message = obj.(string)
}
}
ctx.JSON(500, map[string]interface{}{
"message": message,
"documentation_url": setting.API.SwaggerURL,
"errors": errors,
})
}
func (ctx *APIContext) FileExistError(objs ...interface{}){
var message = "file does not exist"
var errors []string
for _, obj := range objs {
// Ignore nil
if obj == nil {
continue
}
if err, ok := obj.(error); ok {
errors = append(errors, err.Error())
} else {
message = obj.(string)
}
}
ctx.JSON(500, map[string]interface{}{
"message": message,
"documentation_url": setting.API.SwaggerURL,
"errors": errors,
})
}
func (ctx *APIContext) CheckHasWiki(objs ...interface{}){
var message = "No wikies"
var errors []string
for _, obj := range objs {
// Ignore nil
if obj == nil {
continue
}
if err, ok := obj.(error); ok {
errors = append(errors, err.Error())
} else {
message = obj.(string)
}
}
ctx.JSON(500, map[string]interface{}{
"message": message,
"documentation_url": setting.API.SwaggerURL,
"errors": errors,
})
}

View File

@ -46,6 +46,7 @@ type Context struct {
Repo *Repository Repo *Repository
Org *Organization Org *Organization
} }
// IsUserSiteAdmin returns true if current user is a site admin // IsUserSiteAdmin returns true if current user is a site admin

View File

@ -5,6 +5,7 @@
package convert package convert
import ( import (
"encoding/json"
"fmt" "fmt"
"time" "time"
@ -29,8 +30,19 @@ func ToEmail(email *models.EmailAddress) *api.Email {
} }
} }
type BranchKind int
const (
None BranchKind = iota
DefaultBranch
ProtectedBranch
OtherBranch
)
// ToBranch convert a git.Commit and git.Branch to an api.Branch // ToBranch convert a git.Commit and git.Branch to an api.Branch
func ToBranch(repo *models.Repository, b *git.Branch, c *git.Commit, bp *models.ProtectedBranch, user *models.User, isRepoAdmin bool) (*api.Branch, error) { func ToBranch(repo *models.Repository, b *git.Branch, c *git.Commit, bp *models.ProtectedBranch, user *models.User, isRepoAdmin bool) (*api.Branch, error) {
var branchKind BranchKind
if bp == nil { if bp == nil {
var hasPerm bool var hasPerm bool
var err error var err error
@ -40,9 +52,15 @@ func ToBranch(repo *models.Repository, b *git.Branch, c *git.Commit, bp *models.
return nil, err return nil, err
} }
} }
if b.Name == repo.DefaultBranch {
branchKind = DefaultBranch
} else {
branchKind = OtherBranch
}
return &api.Branch{ return &api.Branch{
Name: b.Name, Name: b.Name,
CommitID: c.ID.String(), //add configure
Commit: ToCommit(repo, c), Commit: ToCommit(repo, c),
Protected: false, Protected: false,
RequiredApprovals: 0, RequiredApprovals: 0,
@ -50,16 +68,28 @@ func ToBranch(repo *models.Repository, b *git.Branch, c *git.Commit, bp *models.
StatusCheckContexts: []string{}, StatusCheckContexts: []string{},
UserCanPush: hasPerm, UserCanPush: hasPerm,
UserCanMerge: hasPerm, UserCanMerge: hasPerm,
CommitTime: c.Author.When.Format(time.RFC3339),
DefaultBranch: repo.DefaultBranch,
BranchKind: int(branchKind),
}, nil }, nil
} }
if b.Name == repo.DefaultBranch {
branchKind = DefaultBranch
} else {
branchKind = ProtectedBranch
}
branch := &api.Branch{ branch := &api.Branch{
Name: b.Name, Name: b.Name,
CommitID: c.ID.String(), // add configure
Commit: ToCommit(repo, c), Commit: ToCommit(repo, c),
Protected: true, Protected: true,
RequiredApprovals: bp.RequiredApprovals, RequiredApprovals: bp.RequiredApprovals,
EnableStatusCheck: bp.EnableStatusCheck, EnableStatusCheck: bp.EnableStatusCheck,
StatusCheckContexts: bp.StatusCheckContexts, StatusCheckContexts: bp.StatusCheckContexts,
CommitTime: c.Author.When.Format(time.RFC3339),
DefaultBranch: repo.DefaultBranch,
BranchKind: int(branchKind),
} }
if isRepoAdmin { if isRepoAdmin {
@ -128,16 +158,42 @@ func ToBranchProtection(bp *models.ProtectedBranch) *api.BranchProtection {
} }
// ToTag convert a git.Tag to an api.Tag // ToTag convert a git.Tag to an api.Tag
// func ToTag(repo *models.Repository, t *git.Tag) *api.Tag {
// return &api.Tag{
// Name: t.Name,
// ID: t.ID.String(),
// Commit: ToCommitMeta(repo, t),
// ZipballURL: util.URLJoin(repo.HTMLURL(), "archive", t.Name+".zip"),
// TarballURL: util.URLJoin(repo.HTMLURL(), "archive", t.Name+".tar.gz"),
// }
// }
func ToTag(repo *models.Repository, t *git.Tag) *api.Tag { func ToTag(repo *models.Repository, t *git.Tag) *api.Tag {
return &api.Tag{ return &api.Tag{
Name: t.Name, Name: t.Name,
ID: t.ID.String(), ID: t.ID.String(),
Commit: ToCommitMeta(repo, t), Commit: ToTagCommit(repo, t),
Tagger: ToCommitUser(t.Tagger),
Message: t.Message,
ZipballURL: util.URLJoin(repo.HTMLURL(), "archive", t.Name+".zip"), ZipballURL: util.URLJoin(repo.HTMLURL(), "archive", t.Name+".zip"),
TarballURL: util.URLJoin(repo.HTMLURL(), "archive", t.Name+".tar.gz"), TarballURL: util.URLJoin(repo.HTMLURL(), "archive", t.Name+".tar.gz"),
} }
} }
func ToTagCommit(repo *models.Repository, t *git.Tag) *api.TagCommit {
commit, err := t.Commit()
if err != nil {
log.Error("Commit", err)
return &api.TagCommit{}
}
return &api.TagCommit{
CommitMeta: ToCommitMeta(repo, t),
Commiter: ToCommitUser(commit.Committer),
Author: ToCommitUser(commit.Author),
Message: commit.CommitMessage,
}
}
// ToCommit convert a git.Commit to api.PayloadCommit // ToCommit convert a git.Commit to api.PayloadCommit
func ToCommit(repo *models.Repository, c *git.Commit) *api.PayloadCommit { func ToCommit(repo *models.Repository, c *git.Commit) *api.PayloadCommit {
authorUsername := "" authorUsername := ""
@ -255,6 +311,7 @@ func ToHook(repoLink string, w *models.Webhook) *api.Hook {
config := map[string]string{ config := map[string]string{
"url": w.URL, "url": w.URL,
"content_type": w.ContentType.Name(), "content_type": w.ContentType.Name(),
"http_method": w.HTTPMethod,
} }
if w.HookTaskType == models.SLACK { if w.HookTaskType == models.SLACK {
s := webhook.GetSlackHook(w) s := webhook.GetSlackHook(w)
@ -268,6 +325,7 @@ func ToHook(repoLink string, w *models.Webhook) *api.Hook {
ID: w.ID, ID: w.ID,
Type: w.HookTaskType.Name(), Type: w.HookTaskType.Name(),
URL: fmt.Sprintf("%s/settings/hooks/%d", repoLink, w.ID), URL: fmt.Sprintf("%s/settings/hooks/%d", repoLink, w.ID),
BranchFilter: w.HookEvent.BranchFilter,
Active: w.IsActive, Active: w.IsActive,
Config: config, Config: config,
Events: w.EventsArray(), Events: w.EventsArray(),
@ -276,6 +334,36 @@ func ToHook(repoLink string, w *models.Webhook) *api.Hook {
} }
} }
func ToHookTask(t *models.HookTask) *api.HookTask {
config := map[string]string{
"url": t.URL,
"content_type": t.ContentType.Name(),
"http_method": t.HTTPMethod,
}
payloadContent := make(map[string]interface{})
requestContent := make(map[string]interface{})
responseContent := make(map[string]interface{})
_ = json.Unmarshal([]byte(t.PayloadContent), &payloadContent)
_ = json.Unmarshal([]byte(t.RequestContent), &requestContent)
_ = json.Unmarshal([]byte(t.ResponseContent), &responseContent)
return &api.HookTask{
ID: t.ID,
UUID: t.UUID,
Type: t.Type.Name(),
Config: config,
PayloadContent: payloadContent,
EventType: string(t.EventType),
IsSSL: t.IsSSL,
IsDelivered: t.IsDelivered,
Delivered: t.Delivered,
IsSucceed: t.IsSucceed,
RequestContent: requestContent,
ResponseContent: responseContent,
}
}
// ToGitHook convert git.Hook to api.GitHook // ToGitHook convert git.Hook to api.GitHook
func ToGitHook(h *git.Hook) *api.GitHook { func ToGitHook(h *git.Hook) *api.GitHook {
return &api.GitHook{ return &api.GitHook{
@ -391,6 +479,16 @@ func ToCommitMeta(repo *models.Repository, tag *git.Tag) *api.CommitMeta {
} }
} }
func ToCommitUserFolk(user *models.User) *api.CommitUser {
return &api.CommitUser{
Identity: api.Identity{
Name: user.Name,
Email: user.Email,
},
Date: user.CreatedUnix.AsTime().String(),
}
}
// ToTopicResponse convert from models.Topic to api.TopicResponse // ToTopicResponse convert from models.Topic to api.TopicResponse
func ToTopicResponse(topic *models.Topic) *api.TopicResponse { func ToTopicResponse(topic *models.Topic) *api.TopicResponse {
return &api.TopicResponse{ return &api.TopicResponse{

View File

@ -5,7 +5,10 @@
package convert package convert
import ( import (
"strings"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
) )
// ToCorrectPageSize makes sure page size is in allowed range. // ToCorrectPageSize makes sure page size is in allowed range.
@ -17,3 +20,36 @@ func ToCorrectPageSize(size int) int {
} }
return size return size
} }
// ToGitServiceType return GitServiceType based on string
func ToGitServiceType(value string) structs.GitServiceType {
switch strings.ToLower(value) {
case "github":
return structs.GithubService
case "gitea":
return structs.GiteaService
case "gitlab":
return structs.GitlabService
case "gogs":
return structs.GogsService
default:
return structs.PlainGitService
}
}
//
func ToBranchType(index int) structs.BranchKind{
switch(index){
case 1:
return structs.DefaultBranch
case 2:
return structs.ProtectedBranch
case 3:
return structs.OtherBranch
default:
return structs.None
}
}

View File

@ -293,6 +293,11 @@ func CommitsCount(repoPath, revision string) (int64, error) {
return commitsCount(repoPath, []string{revision}, []string{}) return commitsCount(repoPath, []string{revision}, []string{})
} }
// CommitsCountByFile returns number of total commits of unitl given revision and file
func CommitsCountByFile(repoPath, revision, file string) (int64, error) {
return commitsCount(repoPath, []string{revision}, []string{file})
}
// CommitsCount returns number of total commits of until current revision. // CommitsCount returns number of total commits of until current revision.
func (c *Commit) CommitsCount() (int64, error) { func (c *Commit) CommitsCount() (int64, error) {
return CommitsCount(c.repo.Path, c.ID.String()) return CommitsCount(c.repo.Path, c.ID.String())
@ -303,6 +308,11 @@ func (c *Commit) CommitsByRange(page, pageSize int) (*list.List, error) {
return c.repo.commitsByRange(c.ID, page, pageSize) return c.repo.commitsByRange(c.ID, page, pageSize)
} }
// CommitsByFileAndRange returns the specific page page commits before current revision and file, every page's number default by CommitsRangeSize
func (c *Commit) CommitsByFileAndRange(file string, page, pageSize int) (*list.List, error) {
return c.repo.CommitsByFileAndRange(c.ID.String(), file, page, pageSize)
}
// CommitsBefore returns all the commits before current revision // CommitsBefore returns all the commits before current revision
func (c *Commit) CommitsBefore() (*list.List, error) { func (c *Commit) CommitsBefore() (*list.List, error) {
return c.repo.getCommitsBefore(c.ID) return c.repo.getCommitsBefore(c.ID)

View File

@ -198,7 +198,6 @@ func (repo *Repository) GetCommitByPath(relpath string) (*Commit, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
commits, err := repo.parsePrettyFormatLogToList(stdout) commits, err := repo.parsePrettyFormatLogToList(stdout)
if err != nil { if err != nil {
return nil, err return nil, err
@ -206,6 +205,19 @@ func (repo *Repository) GetCommitByPath(relpath string) (*Commit, error) {
return commits.Front().Value.(*Commit), nil return commits.Front().Value.(*Commit), nil
} }
// GetFirstAndLastCommitByPath returns the first commit and the last commit of relative path.
func (repo *Repository) GetFirstAndLastCommitByPath(revision, relpath string) (*Commit, *Commit, error) {
stdout, err := NewCommand("log", revision, prettyLogFormat, "--", relpath).RunInDirBytes(repo.Path)
if err != nil {
return nil, nil, err
}
commits, err := repo.parsePrettyFormatLogToList(stdout)
if err != nil {
return nil, nil, err
}
return commits.Front().Value.(*Commit), commits.Back().Value.(*Commit), nil
}
// CommitsRangeSize the default commits range size // CommitsRangeSize the default commits range size
var CommitsRangeSize = 50 var CommitsRangeSize = 50
@ -323,8 +335,8 @@ func (repo *Repository) FileCommitsCount(revision, file string) (int64, error) {
} }
// CommitsByFileAndRange return the commits according revison file and the page // CommitsByFileAndRange return the commits according revison file and the page
func (repo *Repository) CommitsByFileAndRange(revision, file string, page int) (*list.List, error) { func (repo *Repository) CommitsByFileAndRange(revision, file string, page, pageSize int) (*list.List, error) {
stdout, err := NewCommand("log", revision, "--follow", "--skip="+strconv.Itoa((page-1)*50), stdout, err := NewCommand("log", revision, "--follow", "--skip="+strconv.Itoa((page-1)*pageSize),
"--max-count="+strconv.Itoa(CommitsRangeSize), prettyLogFormat, "--", file).RunInDirBytes(repo.Path) "--max-count="+strconv.Itoa(CommitsRangeSize), prettyLogFormat, "--", file).RunInDirBytes(repo.Path)
if err != nil { if err != nil {
return nil, err return nil, err
@ -333,8 +345,8 @@ func (repo *Repository) CommitsByFileAndRange(revision, file string, page int) (
} }
// CommitsByFileAndRangeNoFollow return the commits according revison file and the page // CommitsByFileAndRangeNoFollow return the commits according revison file and the page
func (repo *Repository) CommitsByFileAndRangeNoFollow(revision, file string, page int) (*list.List, error) { func (repo *Repository) CommitsByFileAndRangeNoFollow(revision, file string, page, pageSize int) (*list.List, error) {
stdout, err := NewCommand("log", revision, "--skip="+strconv.Itoa((page-1)*50), stdout, err := NewCommand("log", revision, "--skip="+strconv.Itoa((page-1)*pageSize),
"--max-count="+strconv.Itoa(CommitsRangeSize), prettyLogFormat, "--", file).RunInDirBytes(repo.Path) "--max-count="+strconv.Itoa(CommitsRangeSize), prettyLogFormat, "--", file).RunInDirBytes(repo.Path)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -186,6 +186,16 @@ func (repo *Repository) GetTag(name string) (*Tag, error) {
return tag, nil return tag, nil
} }
func (repo *Repository) GetTagCount() (int64, error) {
stdout, err := NewCommand("tag").RunInDir(repo.Path)
if err != nil {
return 0, err
}
tagNames := strings.Split(strings.TrimRight(stdout, "\n"), "\n")
return int64(len(tagNames)), nil
}
// GetTagInfos returns all tag infos of the repository. // GetTagInfos returns all tag infos of the repository.
func (repo *Repository) GetTagInfos(page, pageSize int) ([]*Tag, error) { func (repo *Repository) GetTagInfos(page, pageSize int) ([]*Tag, error) {
// TODO this a slow implementation, makes one git command per tag // TODO this a slow implementation, makes one git command per tag

View File

@ -5,13 +5,14 @@
package repofiles package repofiles
import ( import (
"code.gitea.io/gitea/modules/log"
"fmt" "fmt"
"net/url" "net/url"
"path" "path"
"strings" "strings"
"time" "time"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
@ -147,8 +148,6 @@ func GetContentsOrList(repo *models.Repository, treePath, ref string) (interface
return fileList, nil return fileList, nil
} }
// GetContents gets the meta data on a file's contents. Ref can be a branch, commit or tag // GetContents gets the meta data on a file's contents. Ref can be a branch, commit or tag
func GetContentsExt(gitRepo *git.Repository, commit *git.Commit, repo *models.Repository, treePath, ref string, forList bool) (*api.ContentsResponse, error) { func GetContentsExt(gitRepo *git.Repository, commit *git.Commit, repo *models.Repository, treePath, ref string, forList bool) (*api.ContentsResponse, error) {
if ref == "" { if ref == "" {
@ -223,8 +222,10 @@ func GetContentsExt(gitRepo *git.Repository, commit *git.Commit,repo *models.Rep
if err != nil { if err != nil {
return nil, err return nil, err
} }
if submodule != nil {
contentsResponse.SubmoduleGitURL = &submodule.URL contentsResponse.SubmoduleGitURL = &submodule.URL
} }
}
// Handle links // Handle links
if entry.IsRegular() || entry.IsLink() { if entry.IsRegular() || entry.IsLink() {
downloadURL, err := url.Parse(fmt.Sprintf("%s/raw/%s/%s/%s", repo.HTMLURL(), refType, ref, treePath)) downloadURL, err := url.Parse(fmt.Sprintf("%s/raw/%s/%s/%s", repo.HTMLURL(), refType, ref, treePath))
@ -254,6 +255,7 @@ func GetContentsExt(gitRepo *git.Repository, commit *git.Commit,repo *models.Rep
return contentsResponse, nil return contentsResponse, nil
} }
// GetContents gets the meta data on a file's contents. Ref can be a branch, commit or tag // GetContents gets the meta data on a file's contents. Ref can be a branch, commit or tag
func GetContents(repo *models.Repository, treePath, ref string, forList bool) (*api.ContentsResponse, error) { func GetContents(repo *models.Repository, treePath, ref string, forList bool) (*api.ContentsResponse, error) {
if ref == "" { if ref == "" {

View File

@ -25,6 +25,7 @@ type Hook struct {
Config map[string]string `json:"config"` Config map[string]string `json:"config"`
Events []string `json:"events"` Events []string `json:"events"`
Active bool `json:"active"` Active bool `json:"active"`
BranchFilter string `json:"branch_filter"`
// swagger:strfmt date-time // swagger:strfmt date-time
Updated time.Time `json:"updated_at"` Updated time.Time `json:"updated_at"`
// swagger:strfmt date-time // swagger:strfmt date-time
@ -34,6 +35,21 @@ type Hook struct {
// HookList represents a list of API hook. // HookList represents a list of API hook.
type HookList []*Hook type HookList []*Hook
type HookTask struct {
ID int64 `json:"id"`
UUID string `json:"uuid"`
Type string `json:"type"`
Config map[string]string `json:"config"`
PayloadContent map[string]interface{} `json:"payload_content"`
EventType string `json:"event_type"`
IsSSL bool `json:"is_ssl"`
IsDelivered bool `json:"is_delivered"`
Delivered int64 `json:"delivered"`
IsSucceed bool `json:"is_succeed"`
RequestContent map[string]interface{} `json:"request_info"`
ResponseContent map[string]interface{} `json:"response_content"`
}
// CreateHookOptionConfig has all config options in it // CreateHookOptionConfig has all config options in it
// required are "content_type" and "url" Required // required are "content_type" and "url" Required
type CreateHookOptionConfig map[string]string type CreateHookOptionConfig map[string]string

View File

@ -1,3 +1,11 @@
/*
* @Description: Do not edit
* @Date: 2021-07-09 10:47:30
* @LastEditors: viletyy
* @Author: viletyy
* @LastEditTime: 2021-09-27 16:46:33
* @FilePath: /gitea-1120-rc1/modules/structs/release.go
*/
// Copyright 2016 The Gitea Authors. All rights reserved. // Copyright 2016 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style // Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
@ -14,6 +22,7 @@ type Release struct {
TagName string `json:"tag_name"` TagName string `json:"tag_name"`
Target string `json:"target_commitish"` Target string `json:"target_commitish"`
Title string `json:"name"` Title string `json:"name"`
Sha1 string `json:"sha"`
Note string `json:"body"` Note string `json:"body"`
URL string `json:"url"` URL string `json:"url"`
HTMLURL string `json:"html_url"` HTMLURL string `json:"html_url"`

View File

@ -5,12 +5,14 @@
package structs package structs
import ( import (
"strings"
"time" "time"
) )
// Branch represents a repository branch // Branch represents a repository branch
type Branch struct { type Branch struct {
Name string `json:"name"` Name string `json:"name"`
CommitID string `json:"commit_id"` // add configure
Commit *PayloadCommit `json:"commit"` Commit *PayloadCommit `json:"commit"`
Protected bool `json:"protected"` Protected bool `json:"protected"`
RequiredApprovals int64 `json:"required_approvals"` RequiredApprovals int64 `json:"required_approvals"`
@ -19,7 +21,56 @@ type Branch struct {
UserCanPush bool `json:"user_can_push"` UserCanPush bool `json:"user_can_push"`
UserCanMerge bool `json:"user_can_merge"` UserCanMerge bool `json:"user_can_merge"`
EffectiveBranchProtectionName string `json:"effective_branch_protection_name"` EffectiveBranchProtectionName string `json:"effective_branch_protection_name"`
CommitTime string `json:"commit_time"` // add configure
DefaultBranch string `json:"default_branch"`
BranchKind int `json:"branch_kind"`
} }
type BranchKind int
const (
None BranchKind = iota
DefaultBranch
ProtectedBranch
OtherBranch
)
func (bk BranchKind) Name() string{
return strings.ToLower(bk.Title())
}
func (bk BranchKind) Title() string {
switch bk {
case DefaultBranch:
return "default"
case ProtectedBranch:
return "protected"
case OtherBranch:
return "other"
}
return ""
}
type BranchesSlice struct {
BranchName string `json:"branch_name"`
// BranchKind int `json:"branch_kind"`
Branches []Branch `json:"branches"`
}
// sort by branchkind
type SortBranch []Branch
func (s SortBranch) Len() int { return len(s) }
func (s SortBranch) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s SortBranch) Less(i, j int) bool { return s[i].BranchKind < s[j].BranchKind}
// sort by CommiTime of the branch
type SortBranchTime []Branch
func (s SortBranchTime) Len() int { return len(s) }
func (s SortBranchTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s SortBranchTime) Less(i, j int) bool { return s[i].CommitTime > s[j].CommitTime}
// BranchProtection represents a branch protection for a repository // BranchProtection represents a branch protection for a repository
type BranchProtection struct { type BranchProtection struct {

View File

@ -1,3 +1,11 @@
/*
* @Description: Do not edit
* @Date: 2021-09-07 17:24:32
* @LastEditors: viletyy
* @Author: viletyy
* @LastEditTime: 2021-09-29 10:16:48
* @FilePath: /gitea-1120-rc1/modules/structs/repo_commit.go
*/
// Copyright 2018 The Gogs Authors. All rights reserved. // Copyright 2018 The Gogs Authors. All rights reserved.
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style // Use of this source code is governed by a MIT-style
@ -38,6 +46,7 @@ type RepoCommit struct {
} }
// Commit contains information generated from a Git commit. // Commit contains information generated from a Git commit.
type SortCommit []Commit
type Commit struct { type Commit struct {
*CommitMeta *CommitMeta
HTMLURL string `json:"html_url"` HTMLURL string `json:"html_url"`
@ -45,8 +54,19 @@ type Commit struct {
Author *User `json:"author"` Author *User `json:"author"`
Committer *User `json:"committer"` Committer *User `json:"committer"`
Parents []*CommitMeta `json:"parents"` Parents []*CommitMeta `json:"parents"`
CommitDate string `json:"commit_date"`
Branch string `json:"branch"`
} }
type CommitsSlice struct {
CommitDate string `json:"commit_date"`
Commits []Commit
}
func (s SortCommit) Len() int { return len(s) }
func (s SortCommit) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s SortCommit) Less(i, j int) bool { return s[i].CommitDate > s[j].CommitDate }
// CommitDateOptions store dates for GIT_AUTHOR_DATE and GIT_COMMITTER_DATE // CommitDateOptions store dates for GIT_AUTHOR_DATE and GIT_COMMITTER_DATE
type CommitDateOptions struct { type CommitDateOptions struct {
// swagger:strfmt date-time // swagger:strfmt date-time

View File

@ -1,3 +1,11 @@
/*
* @Description: Do not edit
* @Date: 2021-09-23 17:10:03
* @LastEditors: viletyy
* @Author: viletyy
* @LastEditTime: 2021-09-24 17:45:38
* @FilePath: /gitea-1120-rc1/modules/structs/repo_tag.go
*/
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style // Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
@ -8,11 +16,20 @@ package structs
type Tag struct { type Tag struct {
Name string `json:"name"` Name string `json:"name"`
ID string `json:"id"` ID string `json:"id"`
Commit *CommitMeta `json:"commit"` Commit *TagCommit `json:"commit"`
Tagger *CommitUser `json:"tagger"`
Message string `json:"message"`
ZipballURL string `json:"zipball_url"` ZipballURL string `json:"zipball_url"`
TarballURL string `json:"tarball_url"` TarballURL string `json:"tarball_url"`
} }
type TagCommit struct {
*CommitMeta
Commiter *CommitUser `json:"commiter"`
Author *CommitUser `json:"author"`
Message string `json:"message"`
}
// AnnotatedTag represents an annotated tag // AnnotatedTag represents an annotated tag
type AnnotatedTag struct { type AnnotatedTag struct {
Tag string `json:"tag"` Tag string `json:"tag"`

50
modules/structs/wiki.go Normal file
View File

@ -0,0 +1,50 @@
/*
* @Date: 2021-08-06 14:28:55
* @LastEditors: viletyy
* @LastEditTime: 2021-08-19 18:00:34
* @FilePath: /gitea-1120-rc1/modules/structs/wiki.go
*/
package structs
type WikiesResponse struct {
WikiMeta
WikiCloneLink CloneLink `json:"wiki_clone_link"`
}
type WikiMeta struct {
Name string `json:"name"`
Commit WikiCommit `json:"commit"`
FirstCommit WikiCommit `json:"-"`
//WikiCloneLink CloneLink `json:"wiki_clone_link"`
}
type WikiCommit struct {
ID string `json:"id"`
Message string `json:"message"`
Author WikiUser `json:"author"`
Commiter WikiUser `json:"-"`
}
type WikiUser struct {
Name string `json:"name"`
Email string `json:"email"`
When int64 `json:"when"`
}
type WikiResponse struct {
WikiMeta
CommitCounts int64 `json:"commit_counts"`
MdContent string `json:"md_content"`
SimpleContent string `json:"simple_content"`
WikiCloneLink CloneLink `json:"wiki_clone_link"`
}
type WikiOption struct {
Name string `json:"name"`
Content string `json:"content"`
CommitMessage string `json:"commit_message"`
}
type CloneLink struct {
SSH string `json:"ssh"`
HTTPS string `json:"https"`
}

308
modules/wikies/wiki.go Normal file
View File

@ -0,0 +1,308 @@
/*
* @Date: 2021-08-06 09:53:43
* @LastEditors: viletyy
* @LastEditTime: 2021-08-19 17:58:21
* @FilePath: /gitea-1120-rc1/modules/wikies/wiki.go
*/
package wikies
import (
"fmt"
"code.gitea.io/gitea/models"
repo_module "code.gitea.io/gitea/modules/repository"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/sync"
"code.gitea.io/gitea/modules/util"
"github.com/unknwon/com"
//"github.com/unknwon/com"
"io/ioutil"
"net/url"
"strings"
//"code.gitea.io/gitea/modules/wikies"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
wiki_service "code.gitea.io/gitea/services/wiki"
)
var (
reservedWikiNames = []string{"_pages", "_new", "_edit", "raw"}
wikiWorkingPool = sync.NewExclusivePool()
)
func nameAllowed(name string) error {
if util.IsStringInSlice(name, reservedWikiNames) {
return models.ErrWikiReservedName{
Title: name,
}
}
return nil
}
func InitWiki(repo *models.Repository) error {
if repo.HasWiki() {
return nil
}
if err := git.InitRepository(repo.WikiPath(), true); err != nil {
return fmt.Errorf("InitRepository: %v", err)
} else if err = repo_module.CreateDelegateHooks(repo.WikiPath()); err != nil {
return fmt.Errorf("createDelegateHooks: %v", err)
}
return nil
}
func FindWikiRepoCommit(ctx *context.APIContext) (*git.Repository, *git.Commit, error) {
wikiRepo, err := git.OpenRepository(ctx.Repo.Repository.WikiPath())
if err != nil {
ctx.ServerError("OpenRepository", err)
return nil, nil, err
}
commit, err := wikiRepo.GetBranchCommit("master")
if err != nil {
return wikiRepo, nil, err
}
return wikiRepo, commit, nil
}
func WikiContentsByName(ctx *context.APIContext, commit *git.Commit, wikiName string) ([]byte, *git.TreeEntry, string, bool) {
pageFilename := wiki_service.NameToFilename(wikiName)
entry, err := findEntryForFile(commit, pageFilename)
if err != nil && !git.IsErrNotExist(err) {
ctx.ServerError("findEntryForFile", err)
return nil, nil, "", false
} else if entry == nil {
return nil, nil, "", true
}
return wikiContentsByEntry(ctx, entry), entry, pageFilename, false
}
func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error) {
entry, err := commit.GetTreeEntryByPath(target)
if err != nil && !git.IsErrNotExist(err) {
return nil, err
}
if entry != nil {
return entry, nil
}
// Then the unescaped, shortest alternative
var unescapedTarget string
if unescapedTarget, err = url.QueryUnescape(target); err != nil {
return nil, err
}
return commit.GetTreeEntryByPath(unescapedTarget)
}
func wikiContentsByEntry(ctx *context.APIContext, entry *git.TreeEntry) []byte {
reader, err := entry.Blob().DataAsync()
if err != nil {
ctx.ServerError("Blob.Data", err)
return nil
}
defer reader.Close()
content, err := ioutil.ReadAll(reader)
if err != nil {
ctx.ServerError("ReadAll", err)
return nil
}
return content
}
func CreateWikiPage(doer *models.User, repo *models.Repository, wikiName, content, message string) error {
return updateWikiPage(doer, repo, "", wikiName, content, message, true)
}
func EditWikiPage(doer *models.User, repo *models.Repository, oldWikiName, newWikiName, content, message string) error {
return updateWikiPage(doer, repo, oldWikiName, newWikiName, content, message, false)
}
func updateWikiPage(doer *models.User, repo *models.Repository, oldWikiName, newWikiName, content, message string, isNew bool) (err error) {
if err = nameAllowed(newWikiName); err != nil {
return err
}
wikiWorkingPool.CheckIn(com.ToStr(repo.ID))
defer wikiWorkingPool.CheckOut(com.ToStr(repo.ID))
if err = InitWiki(repo); err != nil {
return fmt.Errorf("InitWiki: %v", err)
}
hasMasterBranch := git.IsBranchExist(repo.WikiPath(), "master")
basePath, err := models.CreateTemporaryPath("update-wiki")
if err != nil {
return err
}
defer func() {
if err := models.RemoveTemporaryPath(basePath); err != nil {
log.Error("Merge: RemoveTemporaryPath: %s", err)
}
}()
cloneOpts := git.CloneRepoOptions{
Bare: true,
Shared: true,
}
if hasMasterBranch {
cloneOpts.Branch = "master"
}
if err := git.Clone(repo.WikiPath(), basePath, cloneOpts); err != nil {
log.Error("Failed to clone repository: %s (%v)", repo.FullName(), err)
return fmt.Errorf("Failed to clone repository: %s (%v)", repo.FullName(), err)
}
gitRepo, err := git.OpenRepository(basePath)
if err != nil {
log.Error("Unable to open temporary repository: %s (%v)", basePath, err)
return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err)
}
defer gitRepo.Close()
if hasMasterBranch {
if err := gitRepo.ReadTreeToIndex("HEAD"); err != nil {
log.Error("Unable to read HEAD tree to index in: %s %v", basePath, err)
return fmt.Errorf("Unable to read HEAD tree to index in: %s %v", basePath, err)
}
}
newWikiPath := wiki_service.NameToFilename(newWikiName)
if isNew {
filesInIndex, err := gitRepo.LsFiles(newWikiPath)
if err != nil {
log.Error("%v", err)
return err
}
if util.IsStringInSlice(newWikiPath, filesInIndex) {
return models.ErrWikiAlreadyExist{
Title: newWikiPath,
}
}
} else {
oldWikiPath := wiki_service.NameToFilename(oldWikiName)
filesInIndex, err := gitRepo.LsFiles(oldWikiPath)
if err != nil {
log.Error("%v", err)
return err
}
if util.IsStringInSlice(oldWikiPath, filesInIndex) {
err := gitRepo.RemoveFilesFromIndex(oldWikiPath)
if err != nil {
log.Error("%v", err)
return err
}
}
}
// FIXME: The wiki doesn't have lfs support at present - if this changes need to check attributes here
objectHash, err := gitRepo.HashObject(strings.NewReader(content))
if err != nil {
log.Error("%v", err)
return err
}
if err := gitRepo.AddObjectToIndex("100644", objectHash, newWikiPath); err != nil {
log.Error("%v", err)
return err
}
tree, err := gitRepo.WriteTree()
if err != nil {
log.Error("%v", err)
return err
}
commitTreeOpts := git.CommitTreeOpts{
Message: message,
}
sign, signingKey, _ := repo.SignWikiCommit(doer)
if sign {
commitTreeOpts.KeyID = signingKey
} else {
commitTreeOpts.NoGPGSign = true
}
if hasMasterBranch {
commitTreeOpts.Parents = []string{"HEAD"}
}
commitHash, err := gitRepo.CommitTree(doer.NewGitSig(), tree, commitTreeOpts)
if err != nil {
log.Error("%v", err)
return err
}
if err := git.Push(basePath, git.PushOptions{
Remote: "origin",
Branch: fmt.Sprintf("%s:%s%s", commitHash.String(), git.BranchPrefix, "master"),
Env: models.FullPushingEnvironment(
doer,
doer,
repo,
repo.Name+".wiki",
0,
),
}); err != nil {
log.Error("%v", err)
if git.IsErrPushOutOfDate(err) || git.IsErrPushRejected(err) {
return err
}
return fmt.Errorf("Push: %v", err)
}
return nil
}
// NewWikiPost response for wiki create request
func NewWikiPost(ctx *context.APIContext, form api.WikiOption) {
ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page")
ctx.Data["PageIsWiki"] = true
ctx.Data["RequireSimpleMDE"] = true
if util.IsEmptyString(form.Name) {
//ctx.RenderWithErr(ctx.Tr("repo.issues.new.title_empty"), nil, form)
return
}
wikiName := wiki_service.NormalizeWikiName(form.Name)
if len(form.CommitMessage) == 0 {
form.CommitMessage = ctx.Tr("repo.editor.add", form.Name)
}
if err := wiki_service.AddWikiPage(ctx.User, ctx.Repo.Repository, wikiName, form.Content, form.CommitMessage); err != nil {
if models.IsErrWikiReservedName(err) {
ctx.Data["Err_Title"] = true
//ctx.RenderWithErr(ctx.Tr("repo.wiki.reserved_page", wikiName), tplWikiNew, &form)
} else if models.IsErrWikiAlreadyExist(err) {
ctx.Data["Err_Title"] = true
//ctx.RenderWithErr(ctx.Tr("repo.wiki.page_already_exists"), tplWikiNew, &form)
} else {
//ctx.ServerError("AddWikiPage", err)
}
return
}
//ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + wiki_service.NameToSubURL(wikiName))
}
func EditWikiPost(ctx *context.APIContext, form api.WikiOption) {
ctx.Data["Title"] = ctx.Tr("repo.wiki.new_page")
ctx.Data["PageIsWiki"] = true
ctx.Data["RequireSimpleMDE"] = true
oldWikiName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
newWikiName := wiki_service.NormalizeWikiName(form.Name)
//newWikiName, _= url.QueryUnescape(newWikiName)
if len(form.CommitMessage) == 0 {
form.CommitMessage = ctx.Tr("repo.editor.update", form.Name)
}
if err := wiki_service.EditWikiPage(ctx.User, ctx.Repo.Repository, oldWikiName, newWikiName, form.Content, form.CommitMessage); err != nil {
ctx.ServerError("EditWikiPage", err)
return
}
}

View File

@ -65,6 +65,9 @@
package v1 package v1
import ( import (
"net/http"
"strings"
"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"
@ -81,13 +84,33 @@ import (
_ "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" "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"
) )
func MustEnableWiki(ctx *context.Context) {
if !ctx.Repo.CanRead(models.UnitTypeWiki) &&
!ctx.Repo.CanRead(models.UnitTypeExternalWiki) {
if log.IsTrace() {
log.Trace("Permission Denied: User %-v cannot read %-v or %-v of repo %-v\n"+
"User in repo has Permissions: %-+v",
ctx.User,
models.UnitTypeWiki,
models.UnitTypeExternalWiki,
ctx.Repo.Repository,
ctx.Repo.Permission)
}
ctx.NotFound("MustEnableWiki", nil)
return
}
unit, err := ctx.Repo.Repository.GetUnit(models.UnitTypeExternalWiki)
if err == nil {
ctx.Redirect(unit.ExternalWikiConfig().ExternalWikiURL)
return
}
}
func sudo() macaron.Handler { func sudo() macaron.Handler {
return func(ctx *context.APIContext) { return func(ctx *context.APIContext) {
sudo := ctx.Query("sudo") sudo := ctx.Query("sudo")
@ -551,7 +574,6 @@ func RegisterRoutes(m *macaron.Macaron) {
Patch(notify.ReadThread) Patch(notify.ReadThread)
}, reqToken()) }, reqToken())
m.Group("/users", func() { m.Group("/users", func() {
m.Get("/search", user.Search) m.Get("/search", user.Search)
@ -585,7 +607,6 @@ func RegisterRoutes(m *macaron.Macaron) {
}) })
}, reqToken()) }, reqToken())
//数据统计 //数据统计
m.Group("/activity", func() { m.Group("/activity", func() {
m.Get("", report.GetActivity) m.Get("", report.GetActivity)
@ -653,9 +674,8 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Combo("/repositories/:id", reqToken()).Get(repo.GetByID) m.Combo("/repositories/:id", reqToken()).Get(repo.GetByID)
//
m.Group("/repos", func() { m.Group("/repos", func() {
m.Get("/search", repo.Search) m.Get("/search", repo.Search)
m.Get("/issues/search", repo.SearchIssues) m.Get("/issues/search", repo.SearchIssues)
@ -679,7 +699,9 @@ 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.Get("/*", viewfile.ReadmeByPath) // reqRepoReader(models.UnitTypeCode),
})
m.Group("/count", func() { m.Group("/count", func() {
m.Get("", viewfile.CommitCount) //**** m.Get("", viewfile.CommitCount) //****
@ -703,6 +725,17 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Combo("/notifications"). m.Combo("/notifications").
Get(reqToken(), notify.ListRepoNotifications). Get(reqToken(), notify.ListRepoNotifications).
Put(reqToken(), notify.ReadRepoNotifications) Put(reqToken(), notify.ReadRepoNotifications)
m.Group("/wikies", func() {
m.Combo("").Get(repo.WikiList).
Post(bind(api.WikiOption{}), repo.CreateWiki)
m.Group("/:page", func() {
m.Combo("").Get(repo.GetWiki).
Patch(bind(api.WikiOption{}), repo.EditWiki).
Delete(repo.DeleteWiki)
})
})
m.Group("/hooks", func() { m.Group("/hooks", func() {
m.Combo("").Get(repo.ListHooks). m.Combo("").Get(repo.ListHooks).
Post(bind(api.CreateHookOption{}), repo.CreateHook) Post(bind(api.CreateHookOption{}), repo.CreateHook)
@ -711,7 +744,9 @@ func RegisterRoutes(m *macaron.Macaron) {
Patch(bind(api.EditHookOption{}), repo.EditHook). Patch(bind(api.EditHookOption{}), repo.EditHook).
Delete(repo.DeleteHook) Delete(repo.DeleteHook)
m.Post("/tests", context.RepoRef(), repo.TestHook) m.Post("/tests", context.RepoRef(), repo.TestHook)
m.Get("/hooktasks", repo.ListHookTask)
}) })
m.Group("/git", func() { m.Group("/git", func() {
m.Combo("").Get(repo.ListGitHooks) m.Combo("").Get(repo.ListGitHooks)
m.Group("/:id", func() { m.Group("/:id", func() {
@ -757,6 +792,7 @@ func RegisterRoutes(m *macaron.Macaron) {
Post(reqToken(), reqRepoReader(models.UnitTypeCode), bind(api.CreateForkOption{}), repo.CreateFork) Post(reqToken(), reqRepoReader(models.UnitTypeCode), bind(api.CreateForkOption{}), repo.CreateFork)
m.Group("/branches", func() { m.Group("/branches", func() {
m.Get("", repo.ListBranches) m.Get("", repo.ListBranches)
m.Get("/branches_slice", repo.ListBranchesSlice)
m.Get("/*", context.RepoRefByType(context.RepoRefBranch), repo.GetBranch) m.Get("/*", context.RepoRefByType(context.RepoRefBranch), repo.GetBranch)
m.Delete("/*", reqRepoWriter(models.UnitTypeCode), context.RepoRefByType(context.RepoRefBranch), repo.DeleteBranch) m.Delete("/*", reqRepoWriter(models.UnitTypeCode), context.RepoRefByType(context.RepoRefBranch), repo.DeleteBranch)
m.Post("", reqRepoWriter(models.UnitTypeCode), bind(api.CreateBranchRepoOption{}), repo.CreateBranch) m.Post("", reqRepoWriter(models.UnitTypeCode), bind(api.CreateBranchRepoOption{}), repo.CreateBranch)
@ -913,11 +949,16 @@ func RegisterRoutes(m *macaron.Macaron) {
}, reqRepoReader(models.UnitTypeCode)) }, reqRepoReader(models.UnitTypeCode))
m.Group("/commits", func() { m.Group("/commits", func() {
m.Get("", repo.GetAllCommits) m.Get("", repo.GetAllCommits)
m.Group("/:ref", func() { m.Group("/:ref", func() {
m.Get("/status", repo.GetCombinedCommitStatusByRef) m.Get("/status", repo.GetCombinedCommitStatusByRef)
m.Get("/statuses", repo.GetCommitStatusesByRef) m.Get("/statuses", repo.GetCommitStatusesByRef)
}) })
}, reqRepoReader(models.UnitTypeCode)) }, reqRepoReader(models.UnitTypeCode))
m.Get("/commits_slice", repo.GetAllCommitsSliceByTime)
m.Group("/file_commits", func() {
m.Get("/*", repo.GetFileAllCommits)
})
m.Group("/git", func() { m.Group("/git", func() {
m.Group("/commits", func() { m.Group("/commits", func() {
m.Get("/:sha", repo.GetSingleCommit) m.Get("/:sha", repo.GetSingleCommit)

View File

@ -6,6 +6,10 @@
package repo package repo
import ( import (
"fmt"
"net/http"
"sort"
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/convert"
@ -14,8 +18,6 @@ import (
"code.gitea.io/gitea/modules/repofiles" "code.gitea.io/gitea/modules/repofiles"
repo_module "code.gitea.io/gitea/modules/repository" repo_module "code.gitea.io/gitea/modules/repository"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"fmt"
"net/http"
) )
// GetBranch get a branch of a repository // GetBranch get a branch of a repository
@ -45,8 +47,6 @@ func GetBranch(ctx *context.APIContext) {
// "200": // "200":
// "$ref": "#/responses/Branch" // "$ref": "#/responses/Branch"
if ctx.Repo.TreePath != "" { if ctx.Repo.TreePath != "" {
// if TreePath != "", then URL contained extra slashes // if TreePath != "", then URL contained extra slashes
// (i.e. "master/subbranch" instead of "master"), so branch does // (i.e. "master/subbranch" instead of "master"), so branch does
@ -328,6 +328,92 @@ func ListBranches(ctx *context.APIContext) {
ctx.JSON(http.StatusOK, &apiBranches) ctx.JSON(http.StatusOK, &apiBranches)
} }
// ListBranches list all the branches of a repository
func ListBranchesSlice(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/branches/branches_slice repository repoListBranchesSlice
// ---
// summary: List a repository's branches, Group sort.
// 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:
// "200":
// "$ref": "#/responses/BranchList"
//start:=time.Now()
branches, err := repo_module.GetBranches(ctx.Repo.Repository)
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetBranches", err)
return
}
//fmt.Println("***************** *GetBranches:",time.Now().Sub(start)," ",branches,len(branches))
apiBranches := make([]*api.Branch, len(branches))
// add configure
apiBranchesList := []api.Branch{}
for i := range branches {
c, err := branches[i].GetCommit()
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetCommit", err)
return
}
//fmt.Println("****branches[i]:",branches[i])
branchProtection, err := ctx.Repo.Repository.GetBranchProtection(branches[i].Name)
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetBranchProtection", err)
return
}
//fmt.Println("****branchProtection:",branchProtection)
apiBranches[i], err = convert.ToBranch(ctx.Repo.Repository, branches[i], c, branchProtection, ctx.User, ctx.Repo.IsAdmin())
if err != nil {
ctx.Error(http.StatusInternalServerError, "convert.ToBranch", err)
return
}
apiBranchesList = append(apiBranchesList, *apiBranches[i])
//fmt.Println("****apiBranches[i]:",apiBranches[i])
}
ctx.JSON(http.StatusOK, BranchesSliceByProtection(ctx, apiBranchesList))
}
// branches slice. Group by protection
func BranchesSliceByProtection(ctx *context.APIContext, branchList []api.Branch) []api.BranchesSlice {
// group by protection
sort.Sort(api.SortBranch(branchList))
branchSlice := make([]api.BranchesSlice, 0)
i := 0
var j int
for {
if i >= len(branchList) {
break
}
for j = i + 1; j < len(branchList) && (branchList[i].BranchKind == branchList[j].BranchKind); j++ {
}
// get the same branches
sameBranchSlice := branchList[i:j]
// sort by time
sort.Sort(api.SortBranchTime(sameBranchSlice))
branchSlice = append(branchSlice, api.BranchesSlice{
BranchName: convert.ToBranchType(branchList[i].BranchKind).Name(),
Branches: sameBranchSlice,
})
i = j
}
return branchSlice
}
// GetBranchProtection gets a branch protection // GetBranchProtection gets a branch protection
func GetBranchProtection(ctx *context.APIContext) { func GetBranchProtection(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/branch_protections/{name} repository repoGetBranchProtection // swagger:operation GET /repos/{owner}/{repo}/branch_protections/{name} repository repoGetBranchProtection

View File

@ -9,18 +9,19 @@ import (
"fmt" "fmt"
"math" "math"
"net/http" "net/http"
"sort"
"strconv" "strconv"
"time" "time"
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/gitgraph" "code.gitea.io/gitea/modules/gitgraph"
"code.gitea.io/gitea/services/gitdiff" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/validation" "code.gitea.io/gitea/modules/validation"
"code.gitea.io/gitea/routers/api/v1/utils" "code.gitea.io/gitea/routers/api/v1/utils"
"code.gitea.io/gitea/services/gitdiff"
) )
// GetSingleCommit get a commit via sha // GetSingleCommit get a commit via sha
@ -83,6 +84,140 @@ func getCommit(ctx *context.APIContext, identifier string) {
ctx.JSON(http.StatusOK, json) ctx.JSON(http.StatusOK, json)
} }
// GetFileCommits get all commits by path on a repository
func GetFileAllCommits(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/file_commits/{filepath} repository repoGetFileAllCommits
// ---
// summary: Get a list of all commits by filepath from a repository
// 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: filepath
// in: path
// description: filepath of the file to get
// type: string
// required: true
// - name: sha
// in: query
// description: SHA or branch to start listing commits from (usually 'master')
// type: string
// - name: page
// in: query
// description: page number of results to return (1-based)
// type: integer
// - name: limit
// in: query
// description: page size of results
// type: integer
// responses:
// "200":
// "$ref": "#/responses/FileCommitList"
// "404":
// "$ref": "#/responses/notFound"
// "409":
// "$ref": "#/responses/EmptyRepository"
if ctx.Repo.Repository.IsEmpty {
ctx.JSON(http.StatusConflict, api.APIError{
Message: "Git Repository is empty.",
URL: setting.API.SwaggerURL,
})
return
}
gitRepo, err := git.OpenRepository(ctx.Repo.Repository.RepoPath())
if err != nil {
ctx.ServerError("OpenRepository", err)
return
}
defer gitRepo.Close()
listOptions := utils.GetListOptions(ctx)
if listOptions.Page <= 0 {
listOptions.Page = 1
}
if listOptions.PageSize > git.CommitsRangeSize {
listOptions.PageSize = git.CommitsRangeSize
}
sha := ctx.Query("sha")
treePath := ctx.Params("*")
var baseCommit *git.Commit
var commitsCountTotal int64
if len(sha) == 0 {
head, err := gitRepo.GetHEADBranch()
if err != nil {
ctx.ServerError("GetHEADBranch", err)
return
}
baseCommit, err = gitRepo.GetBranchCommit(head.Name)
if err != nil {
ctx.ServerError("GetCommit", err)
return
}
commitsCountTotal, err = git.CommitsCountByFile(gitRepo.Path, head.Name, treePath)
if err != nil {
ctx.ServerError("CommitsCount", err)
return
}
} else {
baseCommit, err = gitRepo.GetCommit(sha)
if err != nil {
ctx.ServerError("GetCommit", err)
return
}
commitsCountTotal, err = git.CommitsCountByFile(gitRepo.Path, sha, treePath)
if err != nil {
ctx.ServerError("CommitsCount", err)
return
}
}
pageCount := int(math.Ceil(float64(commitsCountTotal) / float64(listOptions.PageSize)))
commits, err := baseCommit.CommitsByFileAndRange(treePath, listOptions.Page, listOptions.PageSize)
if err != nil {
ctx.ServerError("CommitsByRange", err)
return
}
userCache := make(map[string]*models.User)
apiCommits := make([]*api.Commit, commits.Len())
i := 0
for commitPointer := commits.Front(); commitPointer != nil; commitPointer = commitPointer.Next() {
commit := commitPointer.Value.(*git.Commit)
apiCommits[i], err = toCommit(ctx, ctx.Repo.Repository, commit, userCache)
if err != nil {
ctx.ServerError("toCommit", err)
return
}
i++
}
ctx.Header().Set("X-Page", strconv.Itoa(listOptions.Page))
ctx.Header().Set("X-PerPage", strconv.Itoa(listOptions.PageSize))
ctx.Header().Set("X-Total", strconv.FormatInt(commitsCountTotal, 10))
ctx.Header().Set("X-PageCount", strconv.Itoa(pageCount))
ctx.Header().Set("X-HasMore", strconv.FormatBool(listOptions.Page < pageCount))
ctx.SetLinkHeader(int(commitsCountTotal), listOptions.PageSize)
ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", commitsCountTotal))
ctx.JSON(http.StatusOK, apiCommits)
}
// GetAllCommits get all commits via // GetAllCommits get all commits via
func GetAllCommits(ctx *context.APIContext) { func GetAllCommits(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/commits repository repoGetAllCommits // swagger:operation GET /repos/{owner}/{repo}/commits repository repoGetAllCommits
@ -189,7 +324,10 @@ func GetAllCommits(ctx *context.APIContext) {
userCache := make(map[string]*models.User) userCache := make(map[string]*models.User)
apiCommits := make([]*api.Commit, commits.Len()) apiCommits := make([]*api.Commit, commits.Len())
// =============================================================
// apiCommitsList := []api.Commit{}
// =================================================================
i := 0 i := 0
for commitPointer := commits.Front(); commitPointer != nil; commitPointer = commitPointer.Next() { for commitPointer := commits.Front(); commitPointer != nil; commitPointer = commitPointer.Next() {
commit := commitPointer.Value.(*git.Commit) commit := commitPointer.Value.(*git.Commit)
@ -200,6 +338,7 @@ func GetAllCommits(ctx *context.APIContext) {
ctx.ServerError("toCommit", err) ctx.ServerError("toCommit", err)
return return
} }
// apiCommitsList = append(apiCommitsList,*apiCommits[i])
i++ i++
} }
@ -214,7 +353,168 @@ func GetAllCommits(ctx *context.APIContext) {
ctx.SetLinkHeader(int(commitsCountTotal), listOptions.PageSize) ctx.SetLinkHeader(int(commitsCountTotal), listOptions.PageSize)
ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", commitsCountTotal)) ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", commitsCountTotal))
ctx.JSON(http.StatusOK, &apiCommits) ctx.JSON(http.StatusOK, apiCommits)
}
// GetAllCommits get all commits via
func GetAllCommitsSliceByTime(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/commits_slice repository repoGetAllCommitsSlice
// ---
// summary: Get a list of all commits from a repository
// 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: sha
// in: query
// description: SHA or branch to start listing commits from (usually 'master')
// type: string
// - name: page
// in: query
// description: page number of results to return (1-based)
// type: integer
// - name: limit
// in: query
// description: page size of results
// type: integer
// responses:
// "200":
// "$ref": "#/responses/CommitList"
// "404":
// "$ref": "#/responses/notFound"
// "409":
// "$ref": "#/responses/EmptyRepository"
if ctx.Repo.Repository.IsEmpty {
ctx.JSON(http.StatusConflict, api.APIError{
Message: "Git Repository is empty.",
URL: setting.API.SwaggerURL,
})
return
}
gitRepo, err := git.OpenRepository(ctx.Repo.Repository.RepoPath())
if err != nil {
ctx.ServerError("OpenRepository", err)
return
}
defer gitRepo.Close()
listOptions := utils.GetListOptions(ctx)
if listOptions.Page <= 0 {
listOptions.Page = 1
}
if listOptions.PageSize > git.CommitsRangeSize {
listOptions.PageSize = git.CommitsRangeSize
}
sha := ctx.Query("sha")
var baseCommit *git.Commit
if len(sha) == 0 {
// no sha supplied - use default branch
head, err := gitRepo.GetHEADBranch()
if err != nil {
ctx.ServerError("GetHEADBranch", err)
return
}
baseCommit, err = gitRepo.GetBranchCommit(head.Name)
if err != nil {
ctx.ServerError("GetCommit", err)
return
}
} else {
// get commit specified by sha
baseCommit, err = gitRepo.GetCommit(sha)
if err != nil {
ctx.ServerError("GetCommit", err)
return
}
}
// Total commit count
commitsCountTotal, err := baseCommit.CommitsCount()
if err != nil {
ctx.ServerError("GetCommitsCount", err)
return
}
pageCount := int(math.Ceil(float64(commitsCountTotal) / float64(listOptions.PageSize)))
// Query commits
commits, err := baseCommit.CommitsByRange(listOptions.Page, listOptions.PageSize)
if err != nil {
ctx.ServerError("CommitsByRange", err)
return
}
userCache := make(map[string]*models.User)
apiCommits := make([]*api.Commit, commits.Len())
apiCommitsList := []api.Commit{}
i := 0
for commitPointer := commits.Front(); commitPointer != nil; commitPointer = commitPointer.Next() {
commit := commitPointer.Value.(*git.Commit)
// Create json struct
apiCommits[i], err = toCommit(ctx, ctx.Repo.Repository, commit, userCache)
if err != nil {
ctx.ServerError("toCommit", err)
return
}
apiCommitsList = append(apiCommitsList, *apiCommits[i])
i++
}
// kept for backwards compatibility
ctx.Header().Set("X-Page", strconv.Itoa(listOptions.Page))
ctx.Header().Set("X-PerPage", strconv.Itoa(listOptions.PageSize))
ctx.Header().Set("X-Total", strconv.FormatInt(commitsCountTotal, 10))
ctx.Header().Set("X-PageCount", strconv.Itoa(pageCount))
ctx.Header().Set("X-HasMore", strconv.FormatBool(listOptions.Page < pageCount))
ctx.SetLinkHeader(int(commitsCountTotal), listOptions.PageSize)
ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", commitsCountTotal))
ctx.JSON(http.StatusOK, CommitSplitSlice(apiCommitsList))
}
func CommitSplitSlice(CommitsList []api.Commit) []api.CommitsSlice {
// sort by time
sort.Sort(api.SortCommit(CommitsList))
Commits := make([]api.CommitsSlice, 0)
i := 0
var j int
for {
if i >= len(CommitsList) {
break
}
// Detect equal CommitData,
for j = i + 1; j < len(CommitsList) && CommitsList[i].CommitDate == CommitsList[j].CommitDate; j++ {
}
// if equal, put commitdata in an array
commitDate := CommitsList[i].CommitDate
commitDatalist := CommitsList[i:j]
i = j // variable value
// get all the values,,,Commits
Commits = append(Commits, api.CommitsSlice{
CommitDate: commitDate,
Commits: commitDatalist,
})
}
return Commits
} }
func toCommit(ctx *context.APIContext, repo *models.Repository, commit *git.Commit, userCache map[string]*models.User) (*api.Commit, error) { func toCommit(ctx *context.APIContext, repo *models.Repository, commit *git.Commit, userCache map[string]*models.User) (*api.Commit, error) {
@ -277,8 +577,9 @@ func toCommit(ctx *context.APIContext, repo *models.Repository, commit *git.Comm
SHA: sha.String(), SHA: sha.String(),
} }
} }
commit.LoadBranchName()
return &api.Commit{ return &api.Commit{
CommitDate: commit.Committer.When.Format("2006-01-02"), // new time format, year-moon-day
CommitMeta: &api.CommitMeta{ CommitMeta: &api.CommitMeta{
URL: repo.APIURL() + "/git/commits/" + commit.ID.String(), URL: repo.APIURL() + "/git/commits/" + commit.ID.String(),
SHA: commit.ID.String(), SHA: commit.ID.String(),
@ -309,14 +610,16 @@ func toCommit(ctx *context.APIContext, repo *models.Repository, commit *git.Comm
Author: apiAuthor, Author: apiAuthor,
Committer: apiCommitter, Committer: apiCommitter,
Parents: apiParents, Parents: apiParents,
Branch: commit.Branch,
}, nil }, nil
} }
// add by qiubing // add by qiubing
// 获取 Graph // 获取 Graph
func GetGraph(ctx *context.APIContext) { func GetGraph(ctx *context.APIContext) {
if ctx.Repo.Repository.IsEmpty { // 项目是否为空 if ctx.Repo.Repository.IsEmpty { // 项目是否为空
ctx.JSON(409, api.APIError{ ctx.JSON(http.StatusConflict, api.APIError{
Message: "Git Repository is empty.", Message: "Git Repository is empty.",
URL: setting.API.SwaggerURL, URL: setting.API.SwaggerURL,
}) })
@ -334,7 +637,7 @@ func GetGraph(ctx *context.APIContext) {
return return
} }
ctx.JSON(200, &graph) ctx.JSON(http.StatusOK, &graph)
} }
// 获取 commit diff // 获取 commit diff
@ -350,7 +653,7 @@ func Diff(ctx *context.APIContext) {
ctx.NotFound("GetDiffCommit", err) ctx.NotFound("GetDiffCommit", err)
return return
} }
ctx.JSON(200, &diff) ctx.JSON(http.StatusOK, &diff)
} }
// 获取文件 blame 信息 // 获取文件 blame 信息
@ -415,7 +718,7 @@ func GetCommitsCount(ctx *context.APIContext) {
ctx.ServerError("GetCommitsCount", err) ctx.ServerError("GetCommitsCount", err)
return return
} }
ctx.JSON(200, &ctx.Repo) ctx.JSON(http.StatusOK, &ctx.Repo)
} }
// end by qiubing // end by qiubing

View File

@ -57,6 +57,11 @@ func GetRawFile(ctx *context.APIContext) {
// description: filepath of the file to get // description: filepath of the file to get
// type: string // type: string
// required: true // 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: // responses:
// 200: // 200:
// description: success // description: success
@ -68,7 +73,14 @@ func GetRawFile(ctx *context.APIContext) {
return return
} }
blob, err := ctx.Repo.Commit.GetBlobByPath(ctx.Repo.TreePath) ref := ctx.QueryTrim("ref")
commit, err := ctx.Repo.GitRepo.GetCommit(ref)
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetCommit", err)
return
}
blob, err := commit.GetBlobByPath(ctx.Repo.TreePath)
if err != nil { if err != nil {
if git.IsErrNotExist(err) { if git.IsErrNotExist(err) {
ctx.NotFound() ctx.NotFound()
@ -528,7 +540,6 @@ func GetContents(ctx *context.APIContext) {
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
start := time.Now() start := time.Now()
if !canReadFiles(ctx.Repo) { if !canReadFiles(ctx.Repo) {

View File

@ -6,6 +6,7 @@
package repo package repo
import ( import (
_ "fmt"
"net/http" "net/http"
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
@ -264,3 +265,56 @@ func DeleteHook(ctx *context.APIContext) {
} }
ctx.Status(http.StatusNoContent) ctx.Status(http.StatusNoContent)
} }
func ListHookTask(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/hooks/{id}/hooktasks repository repoGetHookTasks
// ---
// summary: Get a hooktasks
// 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: id
// in: path
// description: id of the hook
// type: integer
// format: int64
// required: true
// - name: page
// in: query
// description: page number of results to return (1-based)
// type: integer
// - name: limit
// in: query
// description: page size of results
// type: integer
// responses:
// "200":
// "$ref": "#/responses/HookTaskList"
hook, err := utils.GetRepoHook(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":id"))
if err != nil {
ctx.NotFound()
return
}
hookTasks, err := models.GetHookTasksByRepoIDAndHookID(ctx.Repo.Repository.ID, hook.ID, utils.GetListOptions(ctx))
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetHookTasksByRepoIDAndHookID", err)
return
}
apiHookTasks := make([]*api.HookTask, len(hookTasks))
for i := range hookTasks {
apiHookTasks[i] = convert.ToHookTask(hookTasks[i])
}
ctx.JSON(http.StatusOK, &apiHookTasks)
}

View File

@ -5,7 +5,10 @@
package repo package repo
import ( import (
"fmt"
"math"
"net/http" "net/http"
"strconv"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/convert"
@ -56,6 +59,22 @@ func ListTags(ctx *context.APIContext) {
apiTags[i] = convert.ToTag(ctx.Repo.Repository, tags[i]) apiTags[i] = convert.ToTag(ctx.Repo.Repository, tags[i])
} }
tagsCountTotal, err := ctx.Repo.GitRepo.GetTagCount()
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetTagCount", err)
return
}
pageCount := int(math.Ceil(float64(tagsCountTotal) / float64(listOpts.PageSize)))
ctx.Header().Set("X-Page", strconv.Itoa(listOpts.Page))
ctx.Header().Set("X-PerPage", strconv.Itoa(listOpts.PageSize))
ctx.Header().Set("X-Total", strconv.FormatInt(tagsCountTotal, 10))
ctx.Header().Set("X-PageCount", strconv.Itoa(pageCount))
ctx.Header().Set("X-HasMore", strconv.FormatBool(listOpts.Page < pageCount))
ctx.SetLinkHeader(int(tagsCountTotal), listOpts.PageSize)
ctx.Header().Set("X-Total-Count", fmt.Sprintf("%d", tagsCountTotal))
ctx.JSON(http.StatusOK, &apiTags) ctx.JSON(http.StatusOK, &apiTags)
} }

434
routers/api/v1/repo/wiki.go Normal file
View File

@ -0,0 +1,434 @@
package repo
//
import (
"net/http"
"sort"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/markup/markdown"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/wikies"
wiki_service "code.gitea.io/gitea/services/wiki"
)
func WikiList(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/wikies repository repoWikiList
// ---
// summary: List the wikies in a repository
// 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:
// "200":
// "$ref": "#/responses/WikiList"
if !ctx.Repo.Repository.HasWiki() {
ctx.CheckHasWiki()
return
}
repository := ctx.Repo.Repository
wikiCloneLink := repository.CloneWikiLink()
wikiRepo, commit, err := wikies.FindWikiRepoCommit(ctx)
if err != nil {
if wikiRepo != nil {
wikiRepo.Close()
}
return
}
entries, err := commit.ListEntries()
if err != nil {
if wikiRepo != nil {
wikiRepo.Close()
}
return
}
wikiesList := make([]api.WikiesResponse, 0, len(entries))
for _, entry := range entries {
if !entry.IsRegular() {
continue
}
//c, err := wikiRepo.GetCommitByPath(entry.Name())
lastCommit, firstCommit, err := wikiRepo.GetFirstAndLastCommitByPath("master", entry.Name())
if err != nil {
if wikiRepo != nil {
wikiRepo.Close()
}
ctx.ServerError("GetCommit", err)
return
}
wikiName, err := wiki_service.FilenameToName(entry.Name())
if err != nil {
if models.IsErrWikiInvalidFileName(err) {
continue
}
if wikiRepo != nil {
wikiRepo.Close()
}
ctx.ServerError("WikiFilenameToName", err)
return
}
wikiesList = append(wikiesList, api.WikiesResponse{
WikiCloneLink: api.CloneLink{
HTTPS: wikiCloneLink.HTTPS,
SSH: wikiCloneLink.SSH,
},
WikiMeta: api.WikiMeta{
Name: wikiName,
Commit: api.WikiCommit{
Author: api.WikiUser{
Name: lastCommit.Author.Name,
Email: lastCommit.Author.Email,
When: lastCommit.Author.When.Unix(),
},
Commiter: api.WikiUser{
Name: lastCommit.Committer.Name,
Email: lastCommit.Committer.Email,
When: lastCommit.Author.When.Unix(),
},
ID: lastCommit.ID.String(),
Message: lastCommit.Message(),
},
FirstCommit: api.WikiCommit{
Author: api.WikiUser{
Name: firstCommit.Author.Name,
Email: firstCommit.Author.Email,
When: firstCommit.Author.When.Unix(),
},
Commiter: api.WikiUser{
Name: firstCommit.Committer.Name,
Email: firstCommit.Committer.Email,
When: firstCommit.Author.When.Unix(),
},
ID: firstCommit.ID.String(),
Message: firstCommit.Message(),
},
},
})
}
//根据创建时间,按最新的时间排序
sort.Slice(wikiesList, func(i, j int) bool {
return wikiesList[i].FirstCommit.Author.When > wikiesList[j].FirstCommit.Author.When
})
ctx.JSON(http.StatusOK, wikiesList)
}
func GetWiki(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/wikies/{pagename} repository repoGetWiki
// ---
// summary: Get a Wiki
// 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: pagename
// in: path
// description: name of the wikipage
// type: string
// required: true
// responses:
// "200":
// "$ref": "#/responses/Wiki"
wikiRepo, commit, _ := wikies.FindWikiRepoCommit(ctx)
repository := ctx.Repo.Repository
wikiCloneLink := repository.CloneWikiLink()
pageName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
if len(pageName) == 0 {
pageName = "Home"
}
data, entry, pageFilename, noEntry := wikies.WikiContentsByName(ctx, commit, pageName)
if noEntry {
ctx.NotFound()
return
}
if entry == nil || ctx.Written() {
if wikiRepo != nil {
wikiRepo.Close()
}
}
metas := ctx.Repo.Repository.ComposeDocumentMetas()
PageContent := markdown.RenderWiki(data, ctx.Repo.RepoLink, metas)
c, err := wikiRepo.GetCommitByPath(entry.Name())
if err != nil {
if models.IsErrWikiInvalidFileName(err) {
return
}
}
commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename)
wiki := api.WikiResponse{
WikiCloneLink: api.CloneLink{
HTTPS: wikiCloneLink.HTTPS,
SSH: wikiCloneLink.SSH,
},
WikiMeta: api.WikiMeta{
Name: pageName,
Commit: api.WikiCommit{
Author: api.WikiUser{
Name: c.Author.Name,
Email: c.Author.Email,
When: c.Author.When.Unix(),
},
Commiter: api.WikiUser{
Name: c.Committer.Name,
Email: c.Committer.Email,
When: c.Author.When.Unix(),
},
ID: c.ID.String(),
Message: c.Message(),
},
},
CommitCounts: commitsCount,
MdContent: string(data),
SimpleContent: PageContent,
}
ctx.JSON(http.StatusOK, wiki)
}
func CreateWiki(ctx *context.APIContext, form api.WikiOption) {
// swagger:operation POST /repos/{owner}/{repo}/wikies repository repoCreateWiki
// ---
// summary: Create a wiki in a repository
// 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: body
// in: body
// schema:
// "$ref": "#/definitions/WikiOption"
// responses:
// "200":
// "$ref": "#/responses/Wiki"
err1 := wiki_service.CheckFile(form.Name)
if err1 != nil {
ctx.FileNameError()
return
}
repository := ctx.Repo.Repository
wikiCloneLink := repository.CloneWikiLink()
if util.IsEmptyString(form.Name) {
//ctx.RenderWithErr(ctx.Tr("repo.issues.new.title_empty"), nil, form)
return
}
wikiName := wiki_service.NormalizeWikiName(form.Name)
if len(form.CommitMessage) == 0 {
form.CommitMessage = ctx.Tr("repo.editor.add", form.Name)
}
if err := wiki_service.AddWikiPage(ctx.User, ctx.Repo.Repository, wikiName, form.Content, form.CommitMessage); err != nil {
if models.IsErrWikiReservedName(err) {
ctx.Error(http.StatusInternalServerError, "WikiNameIsReservedPage", "wiki名称是被保留的.")
} else if models.IsErrWikiAlreadyExist(err) {
ctx.Error(http.StatusConflict, "WikiNameAlreadyExist", "wiki名称已存在")
} else {
ctx.Error(http.StatusInternalServerError, "AddWikiPage", err)
}
return
}
wikiRepo, commit, _ := wikies.FindWikiRepoCommit(ctx)
data, entry, pageFilename, _ := wikies.WikiContentsByName(ctx, commit, form.Name)
metas := ctx.Repo.Repository.ComposeDocumentMetas()
PageContent := markdown.RenderWiki(data, ctx.Repo.RepoLink, metas)
commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename)
c, err := wikiRepo.GetCommitByPath(entry.Name())
if err != nil {
if models.IsErrWikiInvalidFileName(err) {
return
}
}
wiki := api.WikiResponse{
WikiCloneLink: api.CloneLink{
HTTPS: wikiCloneLink.HTTPS,
SSH: wikiCloneLink.SSH,
},
WikiMeta: api.WikiMeta{
Name: form.Name,
Commit: api.WikiCommit{
Author: api.WikiUser{
Name: c.Author.Name,
Email: c.Author.Email,
When: c.Author.When.Unix(),
},
Commiter: api.WikiUser{
Name: c.Committer.Name,
Email: c.Committer.Email,
When: c.Author.When.Unix(),
},
ID: c.ID.String(),
Message: c.Message(),
},
},
CommitCounts: commitsCount,
MdContent: string(data),
SimpleContent: PageContent,
}
ctx.JSON(http.StatusOK, wiki)
}
func EditWiki(ctx *context.APIContext, form api.WikiOption) {
// swagger:operation PATCH /repos/{owner}/{repo}/wikies/{pagename} repository repoEditWiki
// ---
// summary: Edit a wiki in a repository
// 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: pagename
// in: path
// description: name of the wiki
// type: string
// required: true
// - name: body
// in: body
// schema:
// "$ref": "#/definitions/WikiOption"
// responses:
// "201":
// "$ref": "#/responses/Wiki"
oldWikiName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
newWikiName := wiki_service.NormalizeWikiName(form.Name)
err1 := wiki_service.CheckFile(newWikiName)
if err1 != nil {
ctx.FileNameError()
return
}
wikiRepo, commit, _ := wikies.FindWikiRepoCommit(ctx)
if _, _, _, noEntry := wikies.WikiContentsByName(ctx, commit, oldWikiName); noEntry {
ctx.Error(http.StatusNotFound, "WikiNotFound", "wiki不存在")
return
}
if _, _, _, noEntry := wikies.WikiContentsByName(ctx, commit, newWikiName); oldWikiName != newWikiName && !noEntry {
ctx.Error(http.StatusConflict, "WikiNameAlreadyExist", "wiki名称已存在")
return
}
if len(form.CommitMessage) == 0 {
form.CommitMessage = ctx.Tr("repo.editor.update", form.Name)
}
if err := wiki_service.EditWikiPage(ctx.User, ctx.Repo.Repository, oldWikiName, newWikiName, form.Content, form.CommitMessage); err != nil {
ctx.Error(http.StatusInternalServerError, "EditWikiPage", err)
return
}
_, newCommit, _ := wikies.FindWikiRepoCommit(ctx)
data, entry, pageFilename, _ := wikies.WikiContentsByName(ctx, newCommit, newWikiName)
c, err := wikiRepo.GetCommitByPath(entry.Name())
if err != nil {
if models.IsErrWikiInvalidFileName(err) {
return
}
}
metas := ctx.Repo.Repository.ComposeDocumentMetas()
PageContent := markdown.RenderWiki(data, ctx.Repo.RepoLink, metas)
commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename)
wiki := api.WikiResponse{
WikiMeta: api.WikiMeta{
Name: form.Name,
Commit: api.WikiCommit{
Author: api.WikiUser{
Name: c.Author.Name,
Email: c.Author.Email,
When: c.Author.When.Unix(),
},
Commiter: api.WikiUser{
Name: c.Committer.Name,
Email: c.Committer.Email,
When: c.Author.When.Unix(),
},
ID: c.ID.String(),
Message: c.Message(),
},
},
CommitCounts: commitsCount,
MdContent: string(data),
SimpleContent: PageContent,
}
ctx.JSON(http.StatusOK, wiki)
}
func DeleteWiki(ctx *context.APIContext) {
// swagger:operation DELETE /repos/{owner}/{repo}/wikies/{pagename} repository repoDeleteWiki
// ---
// summary: Delete a wiki in a repository
// 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: pagename
// in: path
// description: name of the wiki
// type: string
// required: true
// responses:
// "204":
// "$ref": "#/responses/empty"
// "500":
// "$ref": "#/responses/noFound"
wikiName := wiki_service.NormalizeWikiName(ctx.Params(":page"))
if len(wikiName) == 0 {
wikiName = "Home"
}
err2 := wiki_service.DeleteWikiPage(ctx.User, ctx.Repo.Repository, wikiName)
if err2 != nil {
ctx.FileExistError()
return
}
}

View File

@ -23,6 +23,9 @@ type swaggerParameterBodies struct {
// in:body // in:body
DeleteEmailOption api.DeleteEmailOption DeleteEmailOption api.DeleteEmailOption
// in:body
WikiOption api.WikiOption
// in:body // in:body
CreateHookOption api.CreateHookOption CreateHookOption api.CreateHookOption
// in:body // in:body

View File

@ -53,6 +53,21 @@ type swaggerResponseBranchProtectionList struct {
// TagList // TagList
// swagger:response TagList // swagger:response TagList
type swaggerResponseTagList struct { type swaggerResponseTagList struct {
// The current page
Page int `json:"X-Page"`
// Commits per page
PerPage int `json:"X-PerPage"`
// Total commit count
Total int `json:"X-Total"`
// Total number of pages
PageCount int `json:"X-PageCount"`
// True if there is another page
HasMore bool `json:"X-HasMore"`
// in:body // in:body
Body []api.Tag `json:"body"` Body []api.Tag `json:"body"`
} }
@ -85,6 +100,20 @@ type swaggerResponseReferenceList struct {
Body []api.Reference `json:"body"` Body []api.Reference `json:"body"`
} }
// Wiki
// swagger:response Wiki
type swaggerResponseWiki struct {
// in:body
Body api.WikiResponse `json:"body"`
}
// WikiList
// swagger:response WikiList
type swaggerResponseWikiList struct {
// in:body
Body api.WikiesResponse `json:"body"`
}
// Hook // Hook
// swagger:response Hook // swagger:response Hook
type swaggerResponseHook struct { type swaggerResponseHook struct {
@ -99,6 +128,13 @@ type swaggerResponseHookList struct {
Body []api.Hook `json:"body"` Body []api.Hook `json:"body"`
} }
// HookTaskList
// swagger:response HookTaskList
type swaggerResponseHookTaskList struct {
// in:body
Body []api.HookTask `json:"body"`
}
// GitHook // GitHook
// swagger:response GitHook // swagger:response GitHook
type swaggerResponseGitHook struct { type swaggerResponseGitHook struct {
@ -254,6 +290,28 @@ type swaggerCommitList struct {
Body []api.Commit `json:"body"` Body []api.Commit `json:"body"`
} }
// FileCommitList
// swagger:response FileCommitList
type swaggerFileCommitList struct {
// The current page
Page int `json:"X-Page"`
// Commits per page
PerPage int `json:"X-PerPage"`
// Total commit count
Total int `json:"X-Total"`
// Total number of pages
PageCount int `json:"X-PageCount"`
// True if there is another page
HasMore bool `json:"X-HasMore"`
// in: body
Body []api.Commit `json:"body"`
}
// EmptyRepository // EmptyRepository
// swagger:response EmptyRepository // swagger:response EmptyRepository
type swaggerEmptyRepository struct { type swaggerEmptyRepository struct {

View File

@ -148,12 +148,24 @@ func GetUserHeatmapData(ctx *context.APIContext) {
// description: username of user to get // description: username of user to get
// type: string // type: string
// required: true // required: true
// - name: start
// in: query
// description: Query start timestamp
// type: string
// required: false
// - name: end
// in: query
// description: Query end timestamp
// type: string
// required: false
// responses: // responses:
// "200": // "200":
// "$ref": "#/responses/UserHeatmapData" // "$ref": "#/responses/UserHeatmapData"
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
timeStampOptions := utils.GetTimestampOptions(ctx)
// Get the user to throw an error if it does not exist // Get the user to throw an error if it does not exist
user, err := models.GetUserByName(ctx.Params(":username")) user, err := models.GetUserByName(ctx.Params(":username"))
if err != nil { if err != nil {
@ -164,8 +176,8 @@ func GetUserHeatmapData(ctx *context.APIContext) {
} }
return return
} }
heatmap, err := models.GetUserHeatMapDataByUserWithTimeStamp(user, timeStampOptions)
heatmap, err := models.GetUserHeatmapDataByUser(user) // heatmap, err := models.GetUserHeatmapDataByUser(user)
if err != nil { if err != nil {
ctx.Error(http.StatusInternalServerError, "GetUserHeatmapDataByUser", err) ctx.Error(http.StatusInternalServerError, "GetUserHeatmapDataByUser", err)
return return

View File

@ -66,6 +66,11 @@ func CheckCreateHookOption(ctx *context.APIContext, form *api.CreateHookOption)
ctx.Error(http.StatusUnprocessableEntity, "", "Invalid content type") ctx.Error(http.StatusUnprocessableEntity, "", "Invalid content type")
return false return false
} }
if !models.IsValidHookHttpMethod(form.Config["http_method"]) {
ctx.Error(http.StatusUnprocessableEntity, "", "Invalid http method")
return false
}
return true return true
} }
@ -101,13 +106,14 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID
if len(form.Events) == 0 { if len(form.Events) == 0 {
form.Events = []string{"push"} form.Events = []string{"push"}
} }
w := &models.Webhook{ w := &models.Webhook{
OrgID: orgID, OrgID: orgID,
RepoID: repoID, RepoID: repoID,
URL: form.Config["url"], URL: form.Config["url"],
ContentType: models.ToHookContentType(form.Config["content_type"]), ContentType: models.ToHookContentType(form.Config["content_type"]),
Secret: form.Config["secret"], Secret: form.Config["secret"],
HTTPMethod: "POST", HTTPMethod: form.Config["http_method"],
HookEvent: &models.HookEvent{ HookEvent: &models.HookEvent{
ChooseEvents: true, ChooseEvents: true,
HookEvents: models.HookEvents{ HookEvents: models.HookEvents{
@ -211,6 +217,9 @@ func editHook(ctx *context.APIContext, form *api.EditHookOption, w *models.Webho
if url, ok := form.Config["url"]; ok { if url, ok := form.Config["url"]; ok {
w.URL = url w.URL = url
} }
if secret, ok := form.Config["secret"]; ok {
w.Secret = secret
}
if ct, ok := form.Config["content_type"]; ok { if ct, ok := form.Config["content_type"]; ok {
if !models.IsValidHookContentType(ct) { if !models.IsValidHookContentType(ct) {
ctx.Error(http.StatusUnprocessableEntity, "", "Invalid content type") ctx.Error(http.StatusUnprocessableEntity, "", "Invalid content type")
@ -219,6 +228,14 @@ func editHook(ctx *context.APIContext, form *api.EditHookOption, w *models.Webho
w.ContentType = models.ToHookContentType(ct) w.ContentType = models.ToHookContentType(ct)
} }
if hm, ok := form.Config["http_method"]; ok {
if !models.IsValidHookHttpMethod(hm) {
ctx.Error(http.StatusUnprocessableEntity, "", "Invalid http method")
return false
}
w.HTTPMethod = hm
}
if w.HookTaskType == models.SLACK { if w.HookTaskType == models.SLACK {
if channel, ok := form.Config["channel"]; ok { if channel, ok := form.Config["channel"]; ok {
meta, err := json.Marshal(&webhook.SlackMeta{ meta, err := json.Marshal(&webhook.SlackMeta{
@ -244,18 +261,25 @@ func editHook(ctx *context.APIContext, form *api.EditHookOption, w *models.Webho
w.SendEverything = false w.SendEverything = false
w.ChooseEvents = true w.ChooseEvents = true
w.Create = com.IsSliceContainsStr(form.Events, string(models.HookEventCreate)) w.Create = com.IsSliceContainsStr(form.Events, string(models.HookEventCreate))
w.Push = com.IsSliceContainsStr(form.Events, string(models.HookEventPush))
w.PullRequest = com.IsSliceContainsStr(form.Events, string(models.HookEventPullRequest))
w.Create = com.IsSliceContainsStr(form.Events, string(models.HookEventCreate))
w.Delete = com.IsSliceContainsStr(form.Events, string(models.HookEventDelete)) w.Delete = com.IsSliceContainsStr(form.Events, string(models.HookEventDelete))
w.Fork = com.IsSliceContainsStr(form.Events, string(models.HookEventFork)) w.Fork = com.IsSliceContainsStr(form.Events, string(models.HookEventFork))
w.Issues = com.IsSliceContainsStr(form.Events, string(models.HookEventIssues)) w.Issues = com.IsSliceContainsStr(form.Events, string(models.HookEventIssues))
w.IssueComment = com.IsSliceContainsStr(form.Events, string(models.HookEventIssueComment)) w.Issues = issuesHook(form.Events, "issues_only")
w.IssueAssign = issuesHook(form.Events, string(models.HookEventIssueAssign))
w.IssueLabel = issuesHook(form.Events, string(models.HookEventIssueLabel))
w.IssueMilestone = issuesHook(form.Events, string(models.HookEventIssueMilestone))
w.IssueComment = issuesHook(form.Events, string(models.HookEventIssueComment))
w.Push = com.IsSliceContainsStr(form.Events, string(models.HookEventPush)) w.Push = com.IsSliceContainsStr(form.Events, string(models.HookEventPush))
w.PullRequest = com.IsSliceContainsStr(form.Events, string(models.HookEventPullRequest)) w.PullRequest = pullHook(form.Events, "pull_request_only")
w.PullRequestAssign = pullHook(form.Events, string(models.HookEventPullRequestAssign))
w.PullRequestLabel = pullHook(form.Events, string(models.HookEventPullRequestLabel))
w.PullRequestMilestone = pullHook(form.Events, string(models.HookEventPullRequestMilestone))
w.PullRequestComment = pullHook(form.Events, string(models.HookEventPullRequestComment))
w.PullRequestReview = pullHook(form.Events, "pull_request_review")
w.PullRequestSync = pullHook(form.Events, string(models.HookEventPullRequestSync))
w.Repository = com.IsSliceContainsStr(form.Events, string(models.HookEventRepository)) w.Repository = com.IsSliceContainsStr(form.Events, string(models.HookEventRepository))
w.Release = com.IsSliceContainsStr(form.Events, string(models.HookEventRelease)) w.Release = com.IsSliceContainsStr(form.Events, string(models.HookEventRelease))
w.BranchFilter = form.BranchFilter w.HookEvent.BranchFilter = form.BranchFilter
if err := w.UpdateEvent(); err != nil { if err := w.UpdateEvent(); err != nil {
ctx.Error(http.StatusInternalServerError, "UpdateEvent", err) ctx.Error(http.StatusInternalServerError, "UpdateEvent", err)

View File

@ -11,6 +11,7 @@ import (
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/convert"
"code.gitea.io/gitea/modules/timeutil"
) )
// GetQueryBeforeSince return parsed time (unix format) from URL query's before and since // GetQueryBeforeSince return parsed time (unix format) from URL query's before and since
@ -46,3 +47,10 @@ func GetListOptions(ctx *context.APIContext) models.ListOptions {
PageSize: convert.ToCorrectPageSize(ctx.QueryInt("limit")), PageSize: convert.ToCorrectPageSize(ctx.QueryInt("limit")),
} }
} }
func GetTimestampOptions(ctx *context.APIContext) models.TimestampOptions {
return models.TimestampOptions{
Start: timeutil.TimeStamp(ctx.QueryInt("start")),
End: timeutil.TimeStamp(ctx.QueryInt("end")),
}
}

View File

@ -2,6 +2,17 @@ package viewfile
import ( import (
"bytes" "bytes"
"encoding/base64"
"fmt"
gotemplate "html/template"
"io/ioutil"
"net/http"
"net/url"
"path"
"path/filepath"
"strconv"
"strings"
"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/charset" "code.gitea.io/gitea/modules/charset"
@ -13,17 +24,7 @@ import (
"code.gitea.io/gitea/modules/repofiles" "code.gitea.io/gitea/modules/repofiles"
repo_module "code.gitea.io/gitea/modules/repository" repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"encoding/base64"
"fmt"
"gitea.com/macaron/macaron" "gitea.com/macaron/macaron"
gotemplate "html/template"
"io/ioutil"
"net/http"
"net/url"
"path"
"path/filepath"
"strconv"
"strings"
) )
func Map2DTO(ctx *context.APIContext) (dto *ReadmeDTO) { func Map2DTO(ctx *context.APIContext) (dto *ReadmeDTO) {
@ -38,7 +39,6 @@ func Map2DTO(ctx *context.APIContext) (dto *ReadmeDTO) {
return return
} }
// RepoRefByType handles repository reference name for a specific type // RepoRefByType handles repository reference name for a specific type
// of repository reference // of repository reference
func RepoRefByType(refType context.RepoRefType) macaron.Handler { func RepoRefByType(refType context.RepoRefType) macaron.Handler {
@ -162,7 +162,6 @@ func RepoRefByType(refType context.RepoRefType) macaron.Handler {
} }
} }
func getRefName(ctx *context.APIContext, pathType context.RepoRefType) string { func getRefName(ctx *context.APIContext, pathType context.RepoRefType) string {
path := ctx.Params("*") path := ctx.Params("*")
switch pathType { switch pathType {
@ -223,8 +222,6 @@ func GetRefType() macaron.Handler {
} }
} }
func CommitCount(ctx *context.APIContext) { func CommitCount(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/count repository Count // swagger:operation GET /repos/{owner}/{repo}/count repository Count
// --- // ---
@ -253,7 +250,6 @@ func CommitCount(ctx *context.APIContext) {
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
ref := ctx.QueryTrim("ref") ref := ctx.QueryTrim("ref")
if ref == "" { if ref == "" {
ref = ctx.Params(":ref") ref = ctx.Params(":ref")
@ -281,7 +277,6 @@ func CommitCount(ctx *context.APIContext) {
}() }()
} }
// Get the commit object for the ref // Get the commit object for the ref
commit, err := ctx.Repo.GitRepo.GetCommit(ref) commit, err := ctx.Repo.GitRepo.GetCommit(ref)
if err != nil || commit == nil { if err != nil || commit == nil {
@ -331,7 +326,6 @@ func CommitCount(ctx *context.APIContext) {
ctx.JSON(http.StatusOK, dto) ctx.JSON(http.StatusOK, dto)
} }
type CountDTO struct { type CountDTO struct {
Branch struct { Branch struct {
CommitCount int64 `json:"commit_count"` CommitCount int64 `json:"commit_count"`
@ -383,7 +377,6 @@ func LatestRelease(ctx *context.APIContext) {
}() }()
} }
release, err := models.GetLatestReleaseByRepoIDExt(ctx.Repo.Repository.ID) release, err := models.GetLatestReleaseByRepoIDExt(ctx.Repo.Repository.ID)
//fmt.Println("****************ctx.Repo.Repository.ID:",ctx.Repo.Repository.ID," ",release," ",err) //fmt.Println("****************ctx.Repo.Repository.ID:",ctx.Repo.Repository.ID," ",release," ",err)
if err != nil { if err != nil {
@ -404,7 +397,6 @@ func LatestRelease(ctx *context.APIContext) {
ctx.JSON(http.StatusOK, release) 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
// --- // ---
@ -512,7 +504,6 @@ func Readme(ctx *context.APIContext) {
} }
} }
ctx.Data["Paths"] = paths ctx.Data["Paths"] = paths
ctx.Data["TreeLink"] = treeLink ctx.Data["TreeLink"] = treeLink
ctx.Data["TreeNames"] = treeNames ctx.Data["TreeNames"] = treeNames
@ -528,6 +519,78 @@ func Readme(ctx *context.APIContext) {
} }
/////////////
func ReadmeByPath(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/readme/{dir} repository readmePathContents
// ---
// summary: Gets the metadata and contents (if a file) of an entry in a repository, or a list of entries if a dir
// 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: dir
// in: path
// description: name of the path
// 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/ContentsResponse"
// "404":
// "$ref": "#/responses/notFound"
treePath := ctx.Params("*")
ref := ctx.QueryTrim("ref")
if ref == "" {
ref = ctx.Params(":ref")
if ref == "" {
ref = ctx.Repo.Repository.DefaultBranch
}
}
namedBlob, err := getReadmeFileFromPathExt(ctx, treePath, ref)
if err != nil || namedBlob == nil {
// ctx.NotFound("getReadmeFileFromPath", err)
fileList, err1 := repofiles.GetContentsOrList(ctx.Repo.Repository, treePath, ref)
if err1 != nil {
if git.IsErrNotExist(err1) {
ctx.NotFound("fileList", err1)
return
}
ctx.Error(http.StatusInternalServerError, "GetFileListByPath", err)
} else {
ctx.JSON(http.StatusOK, fileList)
}
} else {
FoundFileItem := namedBlob.name
newTreePath := treePath + "/" + FoundFileItem
contents, err2 := repofiles.GetContents(ctx.Repo.Repository, newTreePath, ref, false)
if err2 != nil {
if git.IsErrNotExist(err2) {
ctx.NotFound("GetReadmeContentByPath", err2)
return
}
ctx.Error(http.StatusInternalServerError, "GetReadmeContentByPath", err)
} else {
ctx.JSON(http.StatusOK, contents)
}
}
}
func ViewFile(ctx *context.APIContext) { func ViewFile(ctx *context.APIContext) {
ctx.Data["Encoding"] = "base64" ctx.Data["Encoding"] = "base64"
@ -606,7 +669,6 @@ func ViewFile(ctx *context.APIContext) {
} }
} }
ctx.Data["Paths"] = paths ctx.Data["Paths"] = paths
ctx.Data["TreeLink"] = treeLink ctx.Data["TreeLink"] = treeLink
ctx.Data["TreeNames"] = treeNames ctx.Data["TreeNames"] = treeNames
@ -798,7 +860,6 @@ func safeURL(address string) string {
return u.String() return u.String()
} }
func linesBytesCount(s []byte) int { func linesBytesCount(s []byte) int {
nl := []byte{'\n'} nl := []byte{'\n'}
n := bytes.Count(s, nl) n := bytes.Count(s, nl)
@ -820,7 +881,6 @@ func linesBytesCount(s []byte) int {
} }
*/ */
// FIXME: There has to be a more efficient way of doing this // FIXME: There has to be a more efficient way of doing this
func getReadmeFileFromPath(commit *git.Commit, treePath string) (*namedBlob, error) { func getReadmeFileFromPath(commit *git.Commit, treePath string) (*namedBlob, error) {
@ -914,7 +974,6 @@ func getReadmeFileFromPathExt(ctx *context.APIContext, treePath, ref string) (*n
}() }()
} }
// Get the commit object for the ref // Get the commit object for the ref
commit, err := ctx.Repo.GitRepo.GetCommit(ref) commit, err := ctx.Repo.GitRepo.GetCommit(ref)
if err != nil { if err != nil {
@ -995,7 +1054,6 @@ func getReadmeFileFromPathExt(ctx *context.APIContext, treePath, ref string) (*n
return readmeFile, nil return readmeFile, nil
} }
func FindFiles(ctx *context.APIContext) { func FindFiles(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/find repository find // swagger:operation GET /repos/{owner}/{repo}/find repository find
// --- // ---
@ -1067,14 +1125,12 @@ func FindFileFromPathExt(ctx *context.APIContext, treePath, ref, key string) (fi
}() }()
} }
// Get the commit object for the ref // Get the commit object for the ref
commit, err := ctx.Repo.GitRepo.GetCommit(ref) commit, err := ctx.Repo.GitRepo.GetCommit(ref)
if err != nil { if err != nil {
return nil, err return nil, err
} }
tree, err := commit.SubTree(treePath) tree, err := commit.SubTree(treePath)
if err != nil { if err != nil {
return nil, err return nil, err
@ -1096,7 +1152,6 @@ func FindFileFromPathExt(ctx *context.APIContext, treePath, ref, key string) (fi
continue continue
} }
fileName := filepath.Base(entry.Name()) fileName := filepath.Base(entry.Name())
if strings.Contains(strings.ToLower(fileName), strings.ToLower(key)) || key == "" { if strings.Contains(strings.ToLower(fileName), strings.ToLower(key)) || key == "" {
@ -1129,7 +1184,6 @@ func FindFileFromPathExt(ctx *context.APIContext, treePath, ref, key string) (fi
} }
htmlURLString := htmlURL.String() htmlURLString := htmlURL.String()
Item := &SearchFileItem{ Item := &SearchFileItem{
Name: fileName, Name: fileName,
Path: treePath, Path: treePath,
@ -1159,7 +1213,6 @@ func FindFileFromPathExt(ctx *context.APIContext, treePath, ref, key string) (fi
return return
} }
type SearchFileItem struct { type SearchFileItem struct {
Name string `json:"name"` Name string `json:"name"`
Path string `json:"path"` Path string `json:"path"`
@ -1189,7 +1242,6 @@ func IsReadmeFileExt(name string, ext ...string) bool {
return name[:7] == "readme_zh." return name[:7] == "readme_zh."
} }
type namedBlob struct { type namedBlob struct {
name string name string
isSymlink bool isSymlink bool

View File

@ -179,7 +179,7 @@ func FileHistory(ctx *context.Context) {
page = 1 page = 1
} }
commits, err := ctx.Repo.GitRepo.CommitsByFileAndRange(branchName, fileName, page) commits, err := ctx.Repo.GitRepo.CommitsByFileAndRange(branchName, fileName, page, 50)
if err != nil { if err != nil {
ctx.ServerError("CommitsByFileAndRange", err) ctx.ServerError("CommitsByFileAndRange", err)
return return

View File

@ -277,7 +277,7 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry)
} }
// get Commit Count // get Commit Count
commitsHistory, err := wikiRepo.CommitsByFileAndRangeNoFollow("master", pageFilename, page) commitsHistory, err := wikiRepo.CommitsByFileAndRangeNoFollow("master", pageFilename, page, 50)
if err != nil { if err != nil {
if wikiRepo != nil { if wikiRepo != nil {
wikiRepo.Close() wikiRepo.Close()

View File

@ -6,6 +6,7 @@
package wiki package wiki
import ( import (
"errors"
"fmt" "fmt"
"net/url" "net/url"
"os" "os"
@ -65,6 +66,16 @@ func FilenameToName(filename string) (string, error) {
} }
return NormalizeWikiName(unescaped), nil return NormalizeWikiName(unescaped), nil
} }
// check filename
func CheckFile(filename string) error {
if(len(filename) <= 150 ){
return nil
}else {
err := errors.New("The name is too long, please be less than 200 bytes")
return err
}
}
// InitWiki initializes a wiki for repository, // InitWiki initializes a wiki for repository,
// it does nothing when repository already has wiki. // it does nothing when repository already has wiki.
@ -134,6 +145,10 @@ func updateWikiPage(doer *models.User, repo *models.Repository, oldWikiName, new
} }
newWikiPath := NameToFilename(newWikiName) newWikiPath := NameToFilename(newWikiName)
//进行url解码
//newWikiPath, _ = url.QueryUnescape(newWikiPath)
if isNew { if isNew {
filesInIndex, err := gitRepo.LsFiles(newWikiPath) filesInIndex, err := gitRepo.LsFiles(newWikiPath)
if err != nil { if err != nil {
@ -170,6 +185,8 @@ func updateWikiPage(doer *models.User, repo *models.Repository, oldWikiName, new
return err return err
} }
fmt.Println("newWikiPath======================",newWikiPath)
if err := gitRepo.AddObjectToIndex("100644", objectHash, newWikiPath); err != nil { if err := gitRepo.AddObjectToIndex("100644", objectHash, newWikiPath); err != nil {
log.Error("%v", err) log.Error("%v", err)
return err return err

View File

@ -21,7 +21,7 @@
}, },
"version": "1.1.1" "version": "1.1.1"
}, },
"basePath": "/api/v1", "basePath": "{{AppSubUrl}}/api/v1",
"paths": { "paths": {
"/activity": { "/activity": {
"get": { "get": {
@ -2443,6 +2443,39 @@
} }
} }
}, },
"/repos/{owner}/{repo}/branches/branches_slice": {
"get": {
"produces": [
"application/json"
],
"tags": [
"repository"
],
"summary": "List a repository's branches, Group sort.",
"operationId": "repoListBranchesSlice",
"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/BranchList"
}
}
}
},
"/repos/{owner}/{repo}/branches/{branch}": { "/repos/{owner}/{repo}/branches/{branch}": {
"get": { "get": {
"produces": [ "produces": [
@ -2810,6 +2843,63 @@
} }
} }
}, },
"/repos/{owner}/{repo}/commits_slice": {
"get": {
"produces": [
"application/json"
],
"tags": [
"repository"
],
"summary": "Get a list of all commits from a repository",
"operationId": "repoGetAllCommitsSlice",
"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
},
{
"type": "string",
"description": "SHA or branch to start listing commits from (usually 'master')",
"name": "sha",
"in": "query"
},
{
"type": "integer",
"description": "page number of results to return (1-based)",
"name": "page",
"in": "query"
},
{
"type": "integer",
"description": "page size of results",
"name": "limit",
"in": "query"
}
],
"responses": {
"200": {
"$ref": "#/responses/CommitList"
},
"404": {
"$ref": "#/responses/notFound"
},
"409": {
"$ref": "#/responses/EmptyRepository"
}
}
}
},
"/repos/{owner}/{repo}/contents": { "/repos/{owner}/{repo}/contents": {
"get": { "get": {
"produces": [ "produces": [
@ -3196,6 +3286,70 @@
} }
} }
}, },
"/repos/{owner}/{repo}/file_commits/{filepath}": {
"get": {
"produces": [
"application/json"
],
"tags": [
"repository"
],
"summary": "Get a list of all commits by filepath from a repository",
"operationId": "repoGetFileAllCommits",
"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
},
{
"type": "string",
"description": "filepath of the file to get",
"name": "filepath",
"in": "path",
"required": true
},
{
"type": "string",
"description": "SHA or branch to start listing commits from (usually 'master')",
"name": "sha",
"in": "query"
},
{
"type": "integer",
"description": "page number of results to return (1-based)",
"name": "page",
"in": "query"
},
{
"type": "integer",
"description": "page size of results",
"name": "limit",
"in": "query"
}
],
"responses": {
"200": {
"$ref": "#/responses/FileCommitList"
},
"404": {
"$ref": "#/responses/notFound"
},
"409": {
"$ref": "#/responses/EmptyRepository"
}
}
}
},
"/repos/{owner}/{repo}/find": { "/repos/{owner}/{repo}/find": {
"get": { "get": {
"produces": [ "produces": [
@ -3988,6 +4142,59 @@
} }
} }
}, },
"/repos/{owner}/{repo}/hooks/{id}/hooktasks": {
"get": {
"produces": [
"application/json"
],
"tags": [
"repository"
],
"summary": "Get a hooktasks",
"operationId": "repoGetHookTasks",
"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
},
{
"type": "integer",
"format": "int64",
"description": "id of the hook",
"name": "id",
"in": "path",
"required": true
},
{
"type": "integer",
"description": "page number of results to return (1-based)",
"name": "page",
"in": "query"
},
{
"type": "integer",
"description": "page size of results",
"name": "limit",
"in": "query"
}
],
"responses": {
"200": {
"$ref": "#/responses/HookTaskList"
}
}
}
},
"/repos/{owner}/{repo}/hooks/{id}/tests": { "/repos/{owner}/{repo}/hooks/{id}/tests": {
"post": { "post": {
"produces": [ "produces": [
@ -7556,6 +7763,12 @@
"name": "filepath", "name": "filepath",
"in": "path", "in": "path",
"required": true "required": true
},
{
"type": "string",
"description": "The name of the commit/branch/tag. Default the repositorys default branch (usually master)",
"name": "ref",
"in": "query"
} }
], ],
"responses": { "responses": {
@ -7610,6 +7823,55 @@
} }
} }
}, },
"/repos/{owner}/{repo}/readme/{dir}": {
"get": {
"produces": [
"application/json"
],
"tags": [
"repository"
],
"summary": "Gets the metadata and contents (if a file) of an entry in a repository, or a list of entries if a dir",
"operationId": "readmePathContents",
"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
},
{
"type": "string",
"description": "name of the path",
"name": "dir",
"in": "path",
"required": true
},
{
"type": "string",
"description": "The name of the commit/branch/tag. Default the repositorys default branch (usually master)",
"name": "ref",
"in": "query"
}
],
"responses": {
"200": {
"$ref": "#/responses/ContentsResponse"
},
"404": {
"$ref": "#/responses/notFound"
}
}
}
},
"/repos/{owner}/{repo}/releases": { "/repos/{owner}/{repo}/releases": {
"get": { "get": {
"produces": [ "produces": [
@ -8847,6 +9109,203 @@
} }
} }
}, },
"/repos/{owner}/{repo}/wikies": {
"get": {
"produces": [
"application/json"
],
"tags": [
"repository"
],
"summary": "List the wikies in a repository",
"operationId": "repoWikiList",
"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/WikiList"
}
}
},
"post": {
"produces": [
"application/json"
],
"tags": [
"repository"
],
"summary": "Create a wiki in a repository",
"operationId": "repoCreateWiki",
"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
},
{
"name": "body",
"in": "body",
"schema": {
"$ref": "#/definitions/WikiOption"
}
}
],
"responses": {
"200": {
"$ref": "#/responses/Wiki"
}
}
}
},
"/repos/{owner}/{repo}/wikies/{pagename}": {
"get": {
"produces": [
"application/json"
],
"tags": [
"repository"
],
"summary": "Get a Wiki",
"operationId": "repoGetWiki",
"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
},
{
"type": "string",
"description": "name of the wikipage",
"name": "pagename",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"$ref": "#/responses/Wiki"
}
}
},
"delete": {
"produces": [
"application/json"
],
"tags": [
"repository"
],
"summary": "Delete a wiki in a repository",
"operationId": "repoDeleteWiki",
"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
},
{
"type": "string",
"description": "name of the wiki",
"name": "pagename",
"in": "path",
"required": true
}
],
"responses": {
"204": {
"$ref": "#/responses/empty"
},
"500": {
"$ref": "#/responses/noFound"
}
}
},
"patch": {
"produces": [
"application/json"
],
"tags": [
"repository"
],
"summary": "Edit a wiki in a repository",
"operationId": "repoEditWiki",
"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
},
{
"type": "string",
"description": "name of the wiki",
"name": "pagename",
"in": "path",
"required": true
},
{
"name": "body",
"in": "body",
"schema": {
"$ref": "#/definitions/WikiOption"
}
}
],
"responses": {
"201": {
"$ref": "#/responses/Wiki"
}
}
}
},
"/repositories/{id}": { "/repositories/{id}": {
"get": { "get": {
"produces": [ "produces": [
@ -10529,6 +10988,18 @@
"name": "username", "name": "username",
"in": "path", "in": "path",
"required": true "required": true
},
{
"type": "string",
"description": "Query start timestamp",
"name": "start",
"in": "query"
},
{
"type": "string",
"description": "Query end timestamp",
"name": "end",
"in": "query"
} }
], ],
"responses": { "responses": {
@ -11041,9 +11512,26 @@
"description": "Branch represents a repository branch", "description": "Branch represents a repository branch",
"type": "object", "type": "object",
"properties": { "properties": {
"branch_kind": {
"type": "integer",
"format": "int64",
"x-go-name": "BranchKind"
},
"commit": { "commit": {
"$ref": "#/definitions/PayloadCommit" "$ref": "#/definitions/PayloadCommit"
}, },
"commit_id": {
"type": "string",
"x-go-name": "CommitID"
},
"commit_time": {
"type": "string",
"x-go-name": "CommitTime"
},
"default_branch": {
"type": "string",
"x-go-name": "DefaultBranch"
},
"effective_branch_protection_name": { "effective_branch_protection_name": {
"type": "string", "type": "string",
"x-go-name": "EffectiveBranchProtectionName" "x-go-name": "EffectiveBranchProtectionName"
@ -11202,6 +11690,20 @@
}, },
"x-go-package": "code.gitea.io/gitea/modules/structs" "x-go-package": "code.gitea.io/gitea/modules/structs"
}, },
"CloneLink": {
"type": "object",
"properties": {
"https": {
"type": "string",
"x-go-name": "HTTPS"
},
"ssh": {
"type": "string",
"x-go-name": "SSH"
}
},
"x-go-package": "code.gitea.io/gitea/modules/structs"
},
"Comment": { "Comment": {
"description": "Comment represents a comment on a commit or issue", "description": "Comment represents a comment on a commit or issue",
"type": "object", "type": "object",
@ -11254,14 +11756,21 @@
}, },
"Commit": { "Commit": {
"type": "object", "type": "object",
"title": "Commit contains information generated from a Git commit.",
"properties": { "properties": {
"author": { "author": {
"$ref": "#/definitions/User" "$ref": "#/definitions/User"
}, },
"branch": {
"type": "string",
"x-go-name": "Branch"
},
"commit": { "commit": {
"$ref": "#/definitions/RepoCommit" "$ref": "#/definitions/RepoCommit"
}, },
"commit_date": {
"type": "string",
"x-go-name": "CommitDate"
},
"committer": { "committer": {
"$ref": "#/definitions/User" "$ref": "#/definitions/User"
}, },
@ -11346,11 +11855,6 @@
"_links": { "_links": {
"$ref": "#/definitions/FileLinksResponse" "$ref": "#/definitions/FileLinksResponse"
}, },
"commit_count": {
"type": "integer",
"format": "int64",
"x-go-name": "CommitCount"
},
"content": { "content": {
"description": "`content` is populated when `type` is `file`, otherwise null", "description": "`content` is populated when `type` is `file`, otherwise null",
"type": "string", "type": "string",
@ -13341,6 +13845,10 @@
"type": "boolean", "type": "boolean",
"x-go-name": "Active" "x-go-name": "Active"
}, },
"branch_filter": {
"type": "string",
"x-go-name": "BranchFilter"
},
"config": { "config": {
"type": "object", "type": "object",
"additionalProperties": { "additionalProperties": {
@ -13377,6 +13885,74 @@
}, },
"x-go-package": "code.gitea.io/gitea/modules/structs" "x-go-package": "code.gitea.io/gitea/modules/structs"
}, },
"HookTask": {
"type": "object",
"properties": {
"config": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"x-go-name": "Config"
},
"delivered": {
"type": "integer",
"format": "int64",
"x-go-name": "Delivered"
},
"event_type": {
"type": "string",
"x-go-name": "EventType"
},
"id": {
"type": "integer",
"format": "int64",
"x-go-name": "ID"
},
"is_delivered": {
"type": "boolean",
"x-go-name": "IsDelivered"
},
"is_ssl": {
"type": "boolean",
"x-go-name": "IsSSL"
},
"is_succeed": {
"type": "boolean",
"x-go-name": "IsSucceed"
},
"payload_content": {
"type": "object",
"additionalProperties": {
"type": "object"
},
"x-go-name": "PayloadContent"
},
"request_info": {
"type": "object",
"additionalProperties": {
"type": "object"
},
"x-go-name": "RequestContent"
},
"response_content": {
"type": "object",
"additionalProperties": {
"type": "object"
},
"x-go-name": "ResponseContent"
},
"type": {
"type": "string",
"x-go-name": "Type"
},
"uuid": {
"type": "string",
"x-go-name": "UUID"
}
},
"x-go-package": "code.gitea.io/gitea/modules/structs"
},
"Identity": { "Identity": {
"description": "Identity for a person's identity like an author or committer", "description": "Identity for a person's identity like an author or committer",
"type": "object", "type": "object",
@ -14430,6 +15006,10 @@
"format": "date-time", "format": "date-time",
"x-go-name": "PublishedAt" "x-go-name": "PublishedAt"
}, },
"sha": {
"type": "string",
"x-go-name": "Sha1"
},
"tag_name": { "tag_name": {
"type": "string", "type": "string",
"x-go-name": "TagName" "x-go-name": "TagName"
@ -14815,16 +15395,23 @@
"type": "object", "type": "object",
"properties": { "properties": {
"commit": { "commit": {
"$ref": "#/definitions/CommitMeta" "$ref": "#/definitions/TagCommit"
}, },
"id": { "id": {
"type": "string", "type": "string",
"x-go-name": "ID" "x-go-name": "ID"
}, },
"message": {
"type": "string",
"x-go-name": "Message"
},
"name": { "name": {
"type": "string", "type": "string",
"x-go-name": "Name" "x-go-name": "Name"
}, },
"tagger": {
"$ref": "#/definitions/CommitUser"
},
"tarball_url": { "tarball_url": {
"type": "string", "type": "string",
"x-go-name": "TarballURL" "x-go-name": "TarballURL"
@ -14836,6 +15423,30 @@
}, },
"x-go-package": "code.gitea.io/gitea/modules/structs" "x-go-package": "code.gitea.io/gitea/modules/structs"
}, },
"TagCommit": {
"type": "object",
"properties": {
"author": {
"$ref": "#/definitions/CommitUser"
},
"commiter": {
"$ref": "#/definitions/CommitUser"
},
"message": {
"type": "string",
"x-go-name": "Message"
},
"sha": {
"type": "string",
"x-go-name": "SHA"
},
"url": {
"type": "string",
"x-go-name": "URL"
}
},
"x-go-package": "code.gitea.io/gitea/modules/structs"
},
"Team": { "Team": {
"description": "Team represents a team in an organization", "description": "Team represents a team in an organization",
"type": "object", "type": "object",
@ -15159,6 +15770,105 @@
} }
}, },
"x-go-package": "code.gitea.io/gitea/modules/structs" "x-go-package": "code.gitea.io/gitea/modules/structs"
},
"WikiCommit": {
"type": "object",
"properties": {
"author": {
"$ref": "#/definitions/WikiUser"
},
"id": {
"type": "string",
"x-go-name": "ID"
},
"message": {
"type": "string",
"x-go-name": "Message"
}
},
"x-go-package": "code.gitea.io/gitea/modules/structs"
},
"WikiOption": {
"type": "object",
"properties": {
"commit_message": {
"type": "string",
"x-go-name": "CommitMessage"
},
"content": {
"type": "string",
"x-go-name": "Content"
},
"name": {
"type": "string",
"x-go-name": "Name"
}
},
"x-go-package": "code.gitea.io/gitea/modules/structs"
},
"WikiResponse": {
"type": "object",
"properties": {
"commit": {
"$ref": "#/definitions/WikiCommit"
},
"commit_counts": {
"type": "integer",
"format": "int64",
"x-go-name": "CommitCounts"
},
"md_content": {
"type": "string",
"x-go-name": "MdContent"
},
"name": {
"type": "string",
"x-go-name": "Name"
},
"simple_content": {
"type": "string",
"x-go-name": "SimpleContent"
},
"wiki_clone_link": {
"$ref": "#/definitions/CloneLink"
}
},
"x-go-package": "code.gitea.io/gitea/modules/structs"
},
"WikiUser": {
"type": "object",
"properties": {
"email": {
"type": "string",
"x-go-name": "Email"
},
"name": {
"type": "string",
"x-go-name": "Name"
},
"when": {
"type": "integer",
"format": "int64",
"x-go-name": "When"
}
},
"x-go-package": "code.gitea.io/gitea/modules/structs"
},
"WikiesResponse": {
"type": "object",
"properties": {
"commit": {
"$ref": "#/definitions/WikiCommit"
},
"name": {
"type": "string",
"x-go-name": "Name"
},
"wiki_clone_link": {
"$ref": "#/definitions/CloneLink"
}
},
"x-go-package": "code.gitea.io/gitea/modules/structs"
} }
}, },
"responses": { "responses": {
@ -15341,6 +16051,41 @@
"$ref": "#/definitions/APIError" "$ref": "#/definitions/APIError"
} }
}, },
"FileCommitList": {
"description": "FileCommitList",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/Commit"
}
},
"headers": {
"X-HasMore": {
"type": "boolean",
"description": "True if there is another page"
},
"X-Page": {
"type": "integer",
"format": "int64",
"description": "The current page"
},
"X-PageCount": {
"type": "integer",
"format": "int64",
"description": "Total number of pages"
},
"X-PerPage": {
"type": "integer",
"format": "int64",
"description": "Commits per page"
},
"X-Total": {
"type": "integer",
"format": "int64",
"description": "Total commit count"
}
}
},
"FileDeleteResponse": { "FileDeleteResponse": {
"description": "FileDeleteResponse", "description": "FileDeleteResponse",
"schema": { "schema": {
@ -15422,6 +16167,15 @@
} }
} }
}, },
"HookTaskList": {
"description": "HookTaskList",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/HookTask"
}
}
},
"Issue": { "Issue": {
"description": "Issue", "description": "Issue",
"schema": { "schema": {
@ -15724,6 +16478,32 @@
"items": { "items": {
"$ref": "#/definitions/Tag" "$ref": "#/definitions/Tag"
} }
},
"headers": {
"X-HasMore": {
"type": "boolean",
"description": "True if there is another page"
},
"X-Page": {
"type": "integer",
"format": "int64",
"description": "The current page"
},
"X-PageCount": {
"type": "integer",
"format": "int64",
"description": "Total number of pages"
},
"X-PerPage": {
"type": "integer",
"format": "int64",
"description": "Commits per page"
},
"X-Total": {
"type": "integer",
"format": "int64",
"description": "Total commit count"
}
} }
}, },
"Team": { "Team": {
@ -15801,6 +16581,18 @@
"$ref": "#/definitions/WatchInfo" "$ref": "#/definitions/WatchInfo"
} }
}, },
"Wiki": {
"description": "Wiki",
"schema": {
"$ref": "#/definitions/WikiResponse"
}
},
"WikiList": {
"description": "WikiList",
"schema": {
"$ref": "#/definitions/WikiesResponse"
}
},
"empty": { "empty": {
"description": "APIEmpty is an empty response" "description": "APIEmpty is an empty response"
}, },

52
vendor/modules.txt vendored
View File

@ -58,7 +58,6 @@ github.com/PuerkitoBio/goquery
# github.com/PuerkitoBio/purell v1.1.1 # github.com/PuerkitoBio/purell v1.1.1
github.com/PuerkitoBio/purell github.com/PuerkitoBio/purell
# github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 # github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578
## explicit
github.com/PuerkitoBio/urlesc github.com/PuerkitoBio/urlesc
# github.com/RoaringBitmap/roaring v0.4.23 # github.com/RoaringBitmap/roaring v0.4.23
## explicit ## explicit
@ -101,15 +100,12 @@ github.com/andybalholm/brotli
# github.com/andybalholm/cascadia v1.1.0 # github.com/andybalholm/cascadia v1.1.0
github.com/andybalholm/cascadia github.com/andybalholm/cascadia
# github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 # github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239
## explicit
github.com/anmitsu/go-shlex github.com/anmitsu/go-shlex
# github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a # github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a
github.com/asaskevich/govalidator github.com/asaskevich/govalidator
# github.com/aymerick/douceur v0.2.0 # github.com/aymerick/douceur v0.2.0
## explicit
github.com/aymerick/douceur/css github.com/aymerick/douceur/css
# github.com/beorn7/perks v1.0.1 # github.com/beorn7/perks v1.0.1
## explicit
github.com/beorn7/perks/quantile github.com/beorn7/perks/quantile
# github.com/bgentry/speakeasy v0.1.0 # github.com/bgentry/speakeasy v0.1.0
## explicit ## explicit
@ -180,7 +176,6 @@ github.com/chris-ramon/douceur/parser
github.com/couchbase/gomemcached github.com/couchbase/gomemcached
github.com/couchbase/gomemcached/client github.com/couchbase/gomemcached/client
# github.com/couchbase/goutils v0.0.0-20191018232750-b49639060d85 # github.com/couchbase/goutils v0.0.0-20191018232750-b49639060d85
## explicit
github.com/couchbase/goutils/logging github.com/couchbase/goutils/logging
github.com/couchbase/goutils/scramsha github.com/couchbase/goutils/scramsha
# github.com/couchbase/vellum v1.0.1 # github.com/couchbase/vellum v1.0.1
@ -199,7 +194,6 @@ github.com/couchbaselabs/go-couchbase
# github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 # github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964
github.com/danwakefield/fnmatch github.com/danwakefield/fnmatch
# github.com/davecgh/go-spew v1.1.1 # github.com/davecgh/go-spew v1.1.1
## explicit
github.com/davecgh/go-spew/spew github.com/davecgh/go-spew/spew
# github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc # github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc
## explicit ## explicit
@ -211,7 +205,6 @@ github.com/denisenkom/go-mssqldb/internal/querytext
## explicit ## explicit
github.com/dgrijalva/jwt-go github.com/dgrijalva/jwt-go
# github.com/dlclark/regexp2 v1.2.0 # github.com/dlclark/regexp2 v1.2.0
## explicit
github.com/dlclark/regexp2 github.com/dlclark/regexp2
github.com/dlclark/regexp2/syntax github.com/dlclark/regexp2/syntax
# github.com/dsnet/compress v0.0.1 # github.com/dsnet/compress v0.0.1
@ -245,10 +238,8 @@ github.com/ethantkoenig/rupture
# github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 # github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870
## explicit ## explicit
# github.com/fatih/color v1.9.0 # github.com/fatih/color v1.9.0
## explicit
github.com/fatih/color github.com/fatih/color
# github.com/fatih/structtag v1.2.0 # github.com/fatih/structtag v1.2.0
## explicit
github.com/fatih/structtag github.com/fatih/structtag
# github.com/fsnotify/fsnotify v1.4.7 # github.com/fsnotify/fsnotify v1.4.7
github.com/fsnotify/fsnotify github.com/fsnotify/fsnotify
@ -269,7 +260,6 @@ github.com/go-enry/go-enry/v2/regex
# github.com/go-enry/go-oniguruma v1.2.1 # github.com/go-enry/go-oniguruma v1.2.1
github.com/go-enry/go-oniguruma github.com/go-enry/go-oniguruma
# github.com/go-git/gcfg v1.5.0 # github.com/go-git/gcfg v1.5.0
## explicit
github.com/go-git/gcfg github.com/go-git/gcfg
github.com/go-git/gcfg/scanner github.com/go-git/gcfg/scanner
github.com/go-git/gcfg/token github.com/go-git/gcfg/token
@ -327,19 +317,12 @@ github.com/go-git/go-git/v5/utils/merkletrie/filesystem
github.com/go-git/go-git/v5/utils/merkletrie/index github.com/go-git/go-git/v5/utils/merkletrie/index
github.com/go-git/go-git/v5/utils/merkletrie/internal/frame github.com/go-git/go-git/v5/utils/merkletrie/internal/frame
github.com/go-git/go-git/v5/utils/merkletrie/noder github.com/go-git/go-git/v5/utils/merkletrie/noder
# github.com/go-macaron/gzip v0.0.0-20200329073552-98214d7a897e
## explicit
# github.com/go-macaron/toolbox v0.0.0-20200329073429-4401f4ce0f55
## explicit
# github.com/go-openapi/analysis v0.19.5 # github.com/go-openapi/analysis v0.19.5
## explicit
github.com/go-openapi/analysis github.com/go-openapi/analysis
github.com/go-openapi/analysis/internal github.com/go-openapi/analysis/internal
# github.com/go-openapi/errors v0.19.2 # github.com/go-openapi/errors v0.19.2
## explicit
github.com/go-openapi/errors github.com/go-openapi/errors
# github.com/go-openapi/inflect v0.19.0 # github.com/go-openapi/inflect v0.19.0
## explicit
github.com/go-openapi/inflect github.com/go-openapi/inflect
# github.com/go-openapi/jsonpointer v0.19.3 # github.com/go-openapi/jsonpointer v0.19.3
github.com/go-openapi/jsonpointer github.com/go-openapi/jsonpointer
@ -347,11 +330,9 @@ github.com/go-openapi/jsonpointer
## explicit ## explicit
github.com/go-openapi/jsonreference github.com/go-openapi/jsonreference
# github.com/go-openapi/loads v0.19.3 # github.com/go-openapi/loads v0.19.3
## explicit
github.com/go-openapi/loads github.com/go-openapi/loads
github.com/go-openapi/loads/fmts github.com/go-openapi/loads/fmts
# github.com/go-openapi/runtime v0.19.5 # github.com/go-openapi/runtime v0.19.5
## explicit
github.com/go-openapi/runtime github.com/go-openapi/runtime
github.com/go-openapi/runtime/logger github.com/go-openapi/runtime/logger
github.com/go-openapi/runtime/middleware github.com/go-openapi/runtime/middleware
@ -360,16 +341,12 @@ github.com/go-openapi/runtime/middleware/header
github.com/go-openapi/runtime/middleware/untyped github.com/go-openapi/runtime/middleware/untyped
github.com/go-openapi/runtime/security github.com/go-openapi/runtime/security
# github.com/go-openapi/spec v0.19.3 # github.com/go-openapi/spec v0.19.3
## explicit
github.com/go-openapi/spec github.com/go-openapi/spec
# github.com/go-openapi/strfmt v0.19.3 # github.com/go-openapi/strfmt v0.19.3
## explicit
github.com/go-openapi/strfmt github.com/go-openapi/strfmt
# github.com/go-openapi/swag v0.19.5 # github.com/go-openapi/swag v0.19.5
## explicit
github.com/go-openapi/swag github.com/go-openapi/swag
# github.com/go-openapi/validate v0.19.3 # github.com/go-openapi/validate v0.19.3
## explicit
github.com/go-openapi/validate github.com/go-openapi/validate
# github.com/go-redis/redis v6.15.2+incompatible # github.com/go-redis/redis v6.15.2+incompatible
## explicit ## explicit
@ -384,7 +361,6 @@ github.com/go-redis/redis/internal/util
## explicit ## explicit
github.com/go-sql-driver/mysql github.com/go-sql-driver/mysql
# github.com/go-stack/stack v1.8.0 # github.com/go-stack/stack v1.8.0
## explicit
github.com/go-stack/stack github.com/go-stack/stack
# github.com/go-swagger/go-swagger v0.21.0 # github.com/go-swagger/go-swagger v0.21.0
## explicit ## explicit
@ -418,20 +394,17 @@ github.com/gogs/cron
# github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe # github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe
github.com/golang-sql/civil github.com/golang-sql/civil
# github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721 # github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721
## explicit
github.com/golang/gddo/httputil github.com/golang/gddo/httputil
github.com/golang/gddo/httputil/header github.com/golang/gddo/httputil/header
# github.com/golang/protobuf v1.4.1 # github.com/golang/protobuf v1.4.1
## explicit ## explicit
github.com/golang/protobuf/proto github.com/golang/protobuf/proto
# github.com/golang/snappy v0.0.1 # github.com/golang/snappy v0.0.1
## explicit
github.com/golang/snappy github.com/golang/snappy
# github.com/google/go-github/v32 v32.1.0 # github.com/google/go-github/v32 v32.1.0
## explicit ## explicit
github.com/google/go-github/v32/github github.com/google/go-github/v32/github
# github.com/google/go-querystring v1.0.0 # github.com/google/go-querystring v1.0.0
## explicit
github.com/google/go-querystring/query github.com/google/go-querystring/query
# github.com/google/uuid v1.1.1 # github.com/google/uuid v1.1.1
## explicit ## explicit
@ -440,10 +413,8 @@ github.com/google/uuid
## explicit ## explicit
github.com/gorilla/context github.com/gorilla/context
# github.com/gorilla/css v1.0.0 # github.com/gorilla/css v1.0.0
## explicit
github.com/gorilla/css/scanner github.com/gorilla/css/scanner
# github.com/gorilla/handlers v1.4.2 # github.com/gorilla/handlers v1.4.2
## explicit
github.com/gorilla/handlers github.com/gorilla/handlers
# github.com/gorilla/mux v1.7.3 # github.com/gorilla/mux v1.7.3
github.com/gorilla/mux github.com/gorilla/mux
@ -483,7 +454,6 @@ github.com/jaytaylor/html2text
# github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 # github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99
github.com/jbenet/go-context/io github.com/jbenet/go-context/io
# github.com/jessevdk/go-flags v1.4.0 # github.com/jessevdk/go-flags v1.4.0
## explicit
github.com/jessevdk/go-flags github.com/jessevdk/go-flags
# github.com/jmhodges/levigo v1.0.0 # github.com/jmhodges/levigo v1.0.0
## explicit ## explicit
@ -519,7 +489,6 @@ github.com/klauspost/compress/zstd/internal/xxhash
# github.com/klauspost/pgzip v1.2.1 # github.com/klauspost/pgzip v1.2.1
github.com/klauspost/pgzip github.com/klauspost/pgzip
# github.com/kr/pretty v0.1.0 # github.com/kr/pretty v0.1.0
## explicit
github.com/kr/pretty github.com/kr/pretty
# github.com/kr/text v0.2.0 # github.com/kr/text v0.2.0
github.com/kr/text github.com/kr/text
@ -536,10 +505,8 @@ github.com/lib/pq/scram
## explicit ## explicit
github.com/lunny/dingtalk_webhook github.com/lunny/dingtalk_webhook
# github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de # github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de
## explicit
github.com/lunny/log github.com/lunny/log
# github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af # github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af
## explicit
github.com/lunny/nodb github.com/lunny/nodb
github.com/lunny/nodb/config github.com/lunny/nodb/config
github.com/lunny/nodb/store github.com/lunny/nodb/store
@ -580,7 +547,6 @@ github.com/mattn/go-runewidth
## explicit ## explicit
github.com/mattn/go-sqlite3 github.com/mattn/go-sqlite3
# github.com/matttproud/golang_protobuf_extensions v1.0.1 # github.com/matttproud/golang_protobuf_extensions v1.0.1
## explicit
github.com/matttproud/golang_protobuf_extensions/pbutil github.com/matttproud/golang_protobuf_extensions/pbutil
# github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75 # github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75
## explicit ## explicit
@ -620,7 +586,6 @@ github.com/niklasfasching/go-org/org
# github.com/nwaples/rardecode v1.0.0 # github.com/nwaples/rardecode v1.0.0
github.com/nwaples/rardecode github.com/nwaples/rardecode
# github.com/olekukonko/tablewriter v0.0.4 # github.com/olekukonko/tablewriter v0.0.4
## explicit
github.com/olekukonko/tablewriter github.com/olekukonko/tablewriter
# github.com/oliamb/cutter v0.2.2 # github.com/oliamb/cutter v0.2.2
## explicit ## explicit
@ -633,17 +598,14 @@ github.com/olivere/elastic/v7/uritemplates
# github.com/pelletier/go-toml v1.4.0 # github.com/pelletier/go-toml v1.4.0
github.com/pelletier/go-toml github.com/pelletier/go-toml
# github.com/philhofer/fwd v1.0.0 # github.com/philhofer/fwd v1.0.0
## explicit
github.com/philhofer/fwd github.com/philhofer/fwd
# github.com/pierrec/lz4 v2.0.5+incompatible # github.com/pierrec/lz4 v2.0.5+incompatible
## explicit
github.com/pierrec/lz4 github.com/pierrec/lz4
github.com/pierrec/lz4/internal/xxh32 github.com/pierrec/lz4/internal/xxh32
# github.com/pkg/errors v0.9.1 # github.com/pkg/errors v0.9.1
## explicit ## explicit
github.com/pkg/errors github.com/pkg/errors
# github.com/pmezard/go-difflib v1.0.0 # github.com/pmezard/go-difflib v1.0.0
## explicit
github.com/pmezard/go-difflib/difflib github.com/pmezard/go-difflib/difflib
# github.com/pquerna/otp v1.2.0 # github.com/pquerna/otp v1.2.0
## explicit ## explicit
@ -659,7 +621,6 @@ github.com/prometheus/client_golang/prometheus/promhttp
## explicit ## explicit
github.com/prometheus/client_model/go github.com/prometheus/client_model/go
# github.com/prometheus/common v0.6.0 # github.com/prometheus/common v0.6.0
## explicit
github.com/prometheus/common/expfmt github.com/prometheus/common/expfmt
github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg
github.com/prometheus/common/model github.com/prometheus/common/model
@ -684,8 +645,9 @@ github.com/shurcooL/httpfs/vfsutil
## explicit ## explicit
github.com/shurcooL/vfsgen github.com/shurcooL/vfsgen
# github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d # github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d
## explicit
github.com/siddontang/go-snappy/snappy github.com/siddontang/go-snappy/snappy
# github.com/smartystreets/goconvey v1.6.4
## explicit
# github.com/spf13/afero v1.2.2 # github.com/spf13/afero v1.2.2
github.com/spf13/afero github.com/spf13/afero
github.com/spf13/afero/mem github.com/spf13/afero/mem
@ -696,7 +658,6 @@ github.com/spf13/jwalterweatherman
# github.com/spf13/pflag v1.0.5 # github.com/spf13/pflag v1.0.5
github.com/spf13/pflag github.com/spf13/pflag
# github.com/spf13/viper v1.4.0 # github.com/spf13/viper v1.4.0
## explicit
github.com/spf13/viper github.com/spf13/viper
# github.com/steveyen/gtreap v0.1.0 # github.com/steveyen/gtreap v0.1.0
github.com/steveyen/gtreap github.com/steveyen/gtreap
@ -705,7 +666,6 @@ github.com/steveyen/gtreap
github.com/stretchr/testify/assert github.com/stretchr/testify/assert
github.com/stretchr/testify/require github.com/stretchr/testify/require
# github.com/syndtr/goleveldb v1.0.0 # github.com/syndtr/goleveldb v1.0.0
## explicit
github.com/syndtr/goleveldb/leveldb github.com/syndtr/goleveldb/leveldb
github.com/syndtr/goleveldb/leveldb/cache github.com/syndtr/goleveldb/leveldb/cache
github.com/syndtr/goleveldb/leveldb/comparer github.com/syndtr/goleveldb/leveldb/comparer
@ -724,7 +684,6 @@ github.com/syndtr/goleveldb/leveldb/util
## explicit ## explicit
github.com/tinylib/msgp/msgp github.com/tinylib/msgp/msgp
# github.com/toqueteos/webbrowser v1.2.0 # github.com/toqueteos/webbrowser v1.2.0
## explicit
github.com/toqueteos/webbrowser github.com/toqueteos/webbrowser
# github.com/tstranex/u2f v1.0.0 # github.com/tstranex/u2f v1.0.0
## explicit ## explicit
@ -778,7 +737,6 @@ github.com/yuin/goldmark-meta
# go.etcd.io/bbolt v1.3.4 # go.etcd.io/bbolt v1.3.4
go.etcd.io/bbolt go.etcd.io/bbolt
# go.mongodb.org/mongo-driver v1.1.1 # go.mongodb.org/mongo-driver v1.1.1
## explicit
go.mongodb.org/mongo-driver/bson go.mongodb.org/mongo-driver/bson
go.mongodb.org/mongo-driver/bson/bsoncodec go.mongodb.org/mongo-driver/bson/bsoncodec
go.mongodb.org/mongo-driver/bson/bsonrw go.mongodb.org/mongo-driver/bson/bsonrw
@ -814,7 +772,6 @@ golang.org/x/crypto/ssh/agent
golang.org/x/crypto/ssh/internal/bcrypt_pbkdf golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
golang.org/x/crypto/ssh/knownhosts golang.org/x/crypto/ssh/knownhosts
# golang.org/x/mod v0.2.0 # golang.org/x/mod v0.2.0
## explicit
golang.org/x/mod/module golang.org/x/mod/module
golang.org/x/mod/semver golang.org/x/mod/semver
# golang.org/x/net v0.0.0-20200602114024-627f9648deb9 # golang.org/x/net v0.0.0-20200602114024-627f9648deb9
@ -891,7 +848,6 @@ golang.org/x/tools/internal/gopathwalk
golang.org/x/tools/internal/imports golang.org/x/tools/internal/imports
golang.org/x/tools/internal/packagesinternal golang.org/x/tools/internal/packagesinternal
# golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 # golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
## explicit
golang.org/x/xerrors golang.org/x/xerrors
golang.org/x/xerrors/internal golang.org/x/xerrors/internal
# google.golang.org/appengine v1.6.5 # google.golang.org/appengine v1.6.5
@ -907,7 +863,6 @@ google.golang.org/appengine/internal/remote_api
google.golang.org/appengine/internal/urlfetch google.golang.org/appengine/internal/urlfetch
google.golang.org/appengine/urlfetch google.golang.org/appengine/urlfetch
# google.golang.org/protobuf v1.22.0 # google.golang.org/protobuf v1.22.0
## explicit
google.golang.org/protobuf/encoding/prototext google.golang.org/protobuf/encoding/prototext
google.golang.org/protobuf/encoding/protowire google.golang.org/protobuf/encoding/protowire
google.golang.org/protobuf/internal/descfmt google.golang.org/protobuf/internal/descfmt
@ -950,10 +905,7 @@ gopkg.in/ini.v1
# gopkg.in/ldap.v3 v3.0.2 # gopkg.in/ldap.v3 v3.0.2
## explicit ## explicit
gopkg.in/ldap.v3 gopkg.in/ldap.v3
# gopkg.in/macaron.v1 v1.4.0
## explicit
# gopkg.in/warnings.v0 v0.1.2 # gopkg.in/warnings.v0 v0.1.2
## explicit
gopkg.in/warnings.v0 gopkg.in/warnings.v0
# gopkg.in/yaml.v2 v2.3.0 # gopkg.in/yaml.v2 v2.3.0
## explicit ## explicit