Merge branch 'main' into lunny/glob_protected_branch_rule
This commit is contained in:
commit
3425685a81
54 changed files with 458 additions and 301 deletions
|
@ -1,6 +1,5 @@
|
||||||
-
|
-
|
||||||
id: 1
|
id: 1
|
||||||
repo_id: 1
|
|
||||||
hook_id: 1
|
hook_id: 1
|
||||||
uuid: uuid1
|
uuid: uuid1
|
||||||
is_delivered: true
|
is_delivered: true
|
||||||
|
|
|
@ -123,6 +123,11 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, err := db.GetEngine(ctx).In("hook_id", builder.Select("id").From("webhook").Where(builder.Eq{"webhook.repo_id": repo.ID})).
|
||||||
|
Delete(&webhook.HookTask{}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if err := db.DeleteBeans(ctx,
|
if err := db.DeleteBeans(ctx,
|
||||||
&access_model.Access{RepoID: repo.ID},
|
&access_model.Access{RepoID: repo.ID},
|
||||||
&activities_model.Action{RepoID: repo.ID},
|
&activities_model.Action{RepoID: repo.ID},
|
||||||
|
@ -130,7 +135,6 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error {
|
||||||
&issues_model.Comment{RefRepoID: repoID},
|
&issues_model.Comment{RefRepoID: repoID},
|
||||||
&git_model.CommitStatus{RepoID: repoID},
|
&git_model.CommitStatus{RepoID: repoID},
|
||||||
&git_model.DeletedBranch{RepoID: repoID},
|
&git_model.DeletedBranch{RepoID: repoID},
|
||||||
&webhook.HookTask{RepoID: repoID},
|
|
||||||
&git_model.LFSLock{RepoID: repoID},
|
&git_model.LFSLock{RepoID: repoID},
|
||||||
&repo_model.LanguageStat{RepoID: repoID},
|
&repo_model.LanguageStat{RepoID: repoID},
|
||||||
&issues_model.Milestone{RepoID: repoID},
|
&issues_model.Milestone{RepoID: repoID},
|
||||||
|
|
|
@ -104,7 +104,6 @@ type HookResponse struct {
|
||||||
// HookTask represents a hook task.
|
// HookTask represents a hook task.
|
||||||
type HookTask struct {
|
type HookTask struct {
|
||||||
ID int64 `xorm:"pk autoincr"`
|
ID int64 `xorm:"pk autoincr"`
|
||||||
RepoID int64 `xorm:"INDEX"`
|
|
||||||
HookID int64
|
HookID int64
|
||||||
UUID string
|
UUID string
|
||||||
api.Payloader `xorm:"-"`
|
api.Payloader `xorm:"-"`
|
||||||
|
@ -178,14 +177,29 @@ func HookTasks(hookID int64, page int) ([]*HookTask, error) {
|
||||||
|
|
||||||
// CreateHookTask creates a new hook task,
|
// CreateHookTask creates a new hook task,
|
||||||
// it handles conversion from Payload to PayloadContent.
|
// it handles conversion from Payload to PayloadContent.
|
||||||
func CreateHookTask(t *HookTask) error {
|
func CreateHookTask(ctx context.Context, t *HookTask) (*HookTask, error) {
|
||||||
data, err := t.Payloader.JSONPayload()
|
data, err := t.Payloader.JSONPayload()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
t.UUID = gouuid.New().String()
|
t.UUID = gouuid.New().String()
|
||||||
t.PayloadContent = string(data)
|
t.PayloadContent = string(data)
|
||||||
return db.Insert(db.DefaultContext, t)
|
return t, db.Insert(ctx, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetHookTaskByID(ctx context.Context, id int64) (*HookTask, error) {
|
||||||
|
t := &HookTask{}
|
||||||
|
|
||||||
|
has, err := db.GetEngine(ctx).ID(id).Get(t)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !has {
|
||||||
|
return nil, ErrHookTaskNotExist{
|
||||||
|
TaskID: id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateHookTask updates information of hook task.
|
// UpdateHookTask updates information of hook task.
|
||||||
|
@ -195,53 +209,36 @@ func UpdateHookTask(t *HookTask) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReplayHookTask copies a hook task to get re-delivered
|
// ReplayHookTask copies a hook task to get re-delivered
|
||||||
func ReplayHookTask(hookID int64, uuid string) (*HookTask, error) {
|
func ReplayHookTask(ctx context.Context, hookID int64, uuid string) (*HookTask, error) {
|
||||||
var newTask *HookTask
|
|
||||||
|
|
||||||
err := db.WithTx(func(ctx context.Context) error {
|
|
||||||
task := &HookTask{
|
task := &HookTask{
|
||||||
HookID: hookID,
|
HookID: hookID,
|
||||||
UUID: uuid,
|
UUID: uuid,
|
||||||
}
|
}
|
||||||
has, err := db.GetByBean(ctx, task)
|
has, err := db.GetByBean(ctx, task)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
} else if !has {
|
} else if !has {
|
||||||
return ErrHookTaskNotExist{
|
return nil, ErrHookTaskNotExist{
|
||||||
HookID: hookID,
|
HookID: hookID,
|
||||||
UUID: uuid,
|
UUID: uuid,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newTask = &HookTask{
|
newTask := &HookTask{
|
||||||
UUID: gouuid.New().String(),
|
UUID: gouuid.New().String(),
|
||||||
RepoID: task.RepoID,
|
|
||||||
HookID: task.HookID,
|
HookID: task.HookID,
|
||||||
PayloadContent: task.PayloadContent,
|
PayloadContent: task.PayloadContent,
|
||||||
EventType: task.EventType,
|
EventType: task.EventType,
|
||||||
}
|
}
|
||||||
return db.Insert(ctx, newTask)
|
return newTask, db.Insert(ctx, newTask)
|
||||||
})
|
|
||||||
|
|
||||||
return newTask, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindUndeliveredHookTasks represents find the undelivered hook tasks
|
// FindUndeliveredHookTasks represents find the undelivered hook tasks
|
||||||
func FindUndeliveredHookTasks() ([]*HookTask, error) {
|
func FindUndeliveredHookTasks(ctx context.Context) ([]*HookTask, error) {
|
||||||
tasks := make([]*HookTask, 0, 10)
|
tasks := make([]*HookTask, 0, 10)
|
||||||
if err := db.GetEngine(db.DefaultContext).Where("is_delivered=?", false).Find(&tasks); err != nil {
|
return tasks, db.GetEngine(ctx).
|
||||||
return nil, err
|
Where("is_delivered=?", false).
|
||||||
}
|
Find(&tasks)
|
||||||
return tasks, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// FindRepoUndeliveredHookTasks represents find the undelivered hook tasks of one repository
|
|
||||||
func FindRepoUndeliveredHookTasks(repoID int64) ([]*HookTask, error) {
|
|
||||||
tasks := make([]*HookTask, 0, 5)
|
|
||||||
if err := db.GetEngine(db.DefaultContext).Where("repo_id=? AND is_delivered=?", repoID, false).Find(&tasks); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return tasks, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CleanupHookTaskTable deletes rows from hook_task as needed.
|
// CleanupHookTaskTable deletes rows from hook_task as needed.
|
||||||
|
@ -250,7 +247,7 @@ func CleanupHookTaskTable(ctx context.Context, cleanupType HookTaskCleanupType,
|
||||||
|
|
||||||
if cleanupType == OlderThan {
|
if cleanupType == OlderThan {
|
||||||
deleteOlderThan := time.Now().Add(-olderThan).UnixNano()
|
deleteOlderThan := time.Now().Add(-olderThan).UnixNano()
|
||||||
deletes, err := db.GetEngine(db.DefaultContext).
|
deletes, err := db.GetEngine(ctx).
|
||||||
Where("is_delivered = ? and delivered < ?", true, deleteOlderThan).
|
Where("is_delivered = ? and delivered < ?", true, deleteOlderThan).
|
||||||
Delete(new(HookTask))
|
Delete(new(HookTask))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -259,7 +256,8 @@ func CleanupHookTaskTable(ctx context.Context, cleanupType HookTaskCleanupType,
|
||||||
log.Trace("Deleted %d rows from hook_task", deletes)
|
log.Trace("Deleted %d rows from hook_task", deletes)
|
||||||
} else if cleanupType == PerWebhook {
|
} else if cleanupType == PerWebhook {
|
||||||
hookIDs := make([]int64, 0, 10)
|
hookIDs := make([]int64, 0, 10)
|
||||||
err := db.GetEngine(db.DefaultContext).Table("webhook").
|
err := db.GetEngine(ctx).
|
||||||
|
Table("webhook").
|
||||||
Where("id > 0").
|
Where("id > 0").
|
||||||
Cols("id").
|
Cols("id").
|
||||||
Find(&hookIDs)
|
Find(&hookIDs)
|
||||||
|
|
|
@ -19,13 +19,6 @@ import (
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
// __ __ ___. .__ __
|
|
||||||
// / \ / \ ____\_ |__ | |__ ____ ____ | | __
|
|
||||||
// \ \/\/ // __ \| __ \| | \ / _ \ / _ \| |/ /
|
|
||||||
// \ /\ ___/| \_\ \ Y ( <_> | <_> ) <
|
|
||||||
// \__/\ / \___ >___ /___| /\____/ \____/|__|_ \
|
|
||||||
// \/ \/ \/ \/ \/
|
|
||||||
|
|
||||||
// ErrWebhookNotExist represents a "WebhookNotExist" kind of error.
|
// ErrWebhookNotExist represents a "WebhookNotExist" kind of error.
|
||||||
type ErrWebhookNotExist struct {
|
type ErrWebhookNotExist struct {
|
||||||
ID int64
|
ID int64
|
||||||
|
@ -47,6 +40,7 @@ func (err ErrWebhookNotExist) Unwrap() error {
|
||||||
|
|
||||||
// ErrHookTaskNotExist represents a "HookTaskNotExist" kind of error.
|
// ErrHookTaskNotExist represents a "HookTaskNotExist" kind of error.
|
||||||
type ErrHookTaskNotExist struct {
|
type ErrHookTaskNotExist struct {
|
||||||
|
TaskID int64
|
||||||
HookID int64
|
HookID int64
|
||||||
UUID string
|
UUID string
|
||||||
}
|
}
|
||||||
|
@ -58,7 +52,7 @@ func IsErrHookTaskNotExist(err error) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (err ErrHookTaskNotExist) Error() string {
|
func (err ErrHookTaskNotExist) Error() string {
|
||||||
return fmt.Sprintf("hook task does not exist [hook: %d, uuid: %s]", err.HookID, err.UUID)
|
return fmt.Sprintf("hook task does not exist [task: %d, hook: %d, uuid: %s]", err.TaskID, err.HookID, err.UUID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (err ErrHookTaskNotExist) Unwrap() error {
|
func (err ErrHookTaskNotExist) Unwrap() error {
|
||||||
|
|
|
@ -208,12 +208,12 @@ func TestHookTasks(t *testing.T) {
|
||||||
func TestCreateHookTask(t *testing.T) {
|
func TestCreateHookTask(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
hookTask := &HookTask{
|
hookTask := &HookTask{
|
||||||
RepoID: 3,
|
|
||||||
HookID: 3,
|
HookID: 3,
|
||||||
Payloader: &api.PushPayload{},
|
Payloader: &api.PushPayload{},
|
||||||
}
|
}
|
||||||
unittest.AssertNotExistsBean(t, hookTask)
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
assert.NoError(t, CreateHookTask(hookTask))
|
_, err := CreateHookTask(db.DefaultContext, hookTask)
|
||||||
|
assert.NoError(t, err)
|
||||||
unittest.AssertExistsAndLoadBean(t, hookTask)
|
unittest.AssertExistsAndLoadBean(t, hookTask)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,14 +232,14 @@ func TestUpdateHookTask(t *testing.T) {
|
||||||
func TestCleanupHookTaskTable_PerWebhook_DeletesDelivered(t *testing.T) {
|
func TestCleanupHookTaskTable_PerWebhook_DeletesDelivered(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
hookTask := &HookTask{
|
hookTask := &HookTask{
|
||||||
RepoID: 3,
|
|
||||||
HookID: 3,
|
HookID: 3,
|
||||||
Payloader: &api.PushPayload{},
|
Payloader: &api.PushPayload{},
|
||||||
IsDelivered: true,
|
IsDelivered: true,
|
||||||
Delivered: time.Now().UnixNano(),
|
Delivered: time.Now().UnixNano(),
|
||||||
}
|
}
|
||||||
unittest.AssertNotExistsBean(t, hookTask)
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
assert.NoError(t, CreateHookTask(hookTask))
|
_, err := CreateHookTask(db.DefaultContext, hookTask)
|
||||||
|
assert.NoError(t, err)
|
||||||
unittest.AssertExistsAndLoadBean(t, hookTask)
|
unittest.AssertExistsAndLoadBean(t, hookTask)
|
||||||
|
|
||||||
assert.NoError(t, CleanupHookTaskTable(context.Background(), PerWebhook, 168*time.Hour, 0))
|
assert.NoError(t, CleanupHookTaskTable(context.Background(), PerWebhook, 168*time.Hour, 0))
|
||||||
|
@ -249,13 +249,13 @@ func TestCleanupHookTaskTable_PerWebhook_DeletesDelivered(t *testing.T) {
|
||||||
func TestCleanupHookTaskTable_PerWebhook_LeavesUndelivered(t *testing.T) {
|
func TestCleanupHookTaskTable_PerWebhook_LeavesUndelivered(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
hookTask := &HookTask{
|
hookTask := &HookTask{
|
||||||
RepoID: 2,
|
|
||||||
HookID: 4,
|
HookID: 4,
|
||||||
Payloader: &api.PushPayload{},
|
Payloader: &api.PushPayload{},
|
||||||
IsDelivered: false,
|
IsDelivered: false,
|
||||||
}
|
}
|
||||||
unittest.AssertNotExistsBean(t, hookTask)
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
assert.NoError(t, CreateHookTask(hookTask))
|
_, err := CreateHookTask(db.DefaultContext, hookTask)
|
||||||
|
assert.NoError(t, err)
|
||||||
unittest.AssertExistsAndLoadBean(t, hookTask)
|
unittest.AssertExistsAndLoadBean(t, hookTask)
|
||||||
|
|
||||||
assert.NoError(t, CleanupHookTaskTable(context.Background(), PerWebhook, 168*time.Hour, 0))
|
assert.NoError(t, CleanupHookTaskTable(context.Background(), PerWebhook, 168*time.Hour, 0))
|
||||||
|
@ -265,14 +265,14 @@ func TestCleanupHookTaskTable_PerWebhook_LeavesUndelivered(t *testing.T) {
|
||||||
func TestCleanupHookTaskTable_PerWebhook_LeavesMostRecentTask(t *testing.T) {
|
func TestCleanupHookTaskTable_PerWebhook_LeavesMostRecentTask(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
hookTask := &HookTask{
|
hookTask := &HookTask{
|
||||||
RepoID: 2,
|
|
||||||
HookID: 4,
|
HookID: 4,
|
||||||
Payloader: &api.PushPayload{},
|
Payloader: &api.PushPayload{},
|
||||||
IsDelivered: true,
|
IsDelivered: true,
|
||||||
Delivered: time.Now().UnixNano(),
|
Delivered: time.Now().UnixNano(),
|
||||||
}
|
}
|
||||||
unittest.AssertNotExistsBean(t, hookTask)
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
assert.NoError(t, CreateHookTask(hookTask))
|
_, err := CreateHookTask(db.DefaultContext, hookTask)
|
||||||
|
assert.NoError(t, err)
|
||||||
unittest.AssertExistsAndLoadBean(t, hookTask)
|
unittest.AssertExistsAndLoadBean(t, hookTask)
|
||||||
|
|
||||||
assert.NoError(t, CleanupHookTaskTable(context.Background(), PerWebhook, 168*time.Hour, 1))
|
assert.NoError(t, CleanupHookTaskTable(context.Background(), PerWebhook, 168*time.Hour, 1))
|
||||||
|
@ -282,14 +282,14 @@ func TestCleanupHookTaskTable_PerWebhook_LeavesMostRecentTask(t *testing.T) {
|
||||||
func TestCleanupHookTaskTable_OlderThan_DeletesDelivered(t *testing.T) {
|
func TestCleanupHookTaskTable_OlderThan_DeletesDelivered(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
hookTask := &HookTask{
|
hookTask := &HookTask{
|
||||||
RepoID: 3,
|
|
||||||
HookID: 3,
|
HookID: 3,
|
||||||
Payloader: &api.PushPayload{},
|
Payloader: &api.PushPayload{},
|
||||||
IsDelivered: true,
|
IsDelivered: true,
|
||||||
Delivered: time.Now().AddDate(0, 0, -8).UnixNano(),
|
Delivered: time.Now().AddDate(0, 0, -8).UnixNano(),
|
||||||
}
|
}
|
||||||
unittest.AssertNotExistsBean(t, hookTask)
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
assert.NoError(t, CreateHookTask(hookTask))
|
_, err := CreateHookTask(db.DefaultContext, hookTask)
|
||||||
|
assert.NoError(t, err)
|
||||||
unittest.AssertExistsAndLoadBean(t, hookTask)
|
unittest.AssertExistsAndLoadBean(t, hookTask)
|
||||||
|
|
||||||
assert.NoError(t, CleanupHookTaskTable(context.Background(), OlderThan, 168*time.Hour, 0))
|
assert.NoError(t, CleanupHookTaskTable(context.Background(), OlderThan, 168*time.Hour, 0))
|
||||||
|
@ -299,13 +299,13 @@ func TestCleanupHookTaskTable_OlderThan_DeletesDelivered(t *testing.T) {
|
||||||
func TestCleanupHookTaskTable_OlderThan_LeavesUndelivered(t *testing.T) {
|
func TestCleanupHookTaskTable_OlderThan_LeavesUndelivered(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
hookTask := &HookTask{
|
hookTask := &HookTask{
|
||||||
RepoID: 2,
|
|
||||||
HookID: 4,
|
HookID: 4,
|
||||||
Payloader: &api.PushPayload{},
|
Payloader: &api.PushPayload{},
|
||||||
IsDelivered: false,
|
IsDelivered: false,
|
||||||
}
|
}
|
||||||
unittest.AssertNotExistsBean(t, hookTask)
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
assert.NoError(t, CreateHookTask(hookTask))
|
_, err := CreateHookTask(db.DefaultContext, hookTask)
|
||||||
|
assert.NoError(t, err)
|
||||||
unittest.AssertExistsAndLoadBean(t, hookTask)
|
unittest.AssertExistsAndLoadBean(t, hookTask)
|
||||||
|
|
||||||
assert.NoError(t, CleanupHookTaskTable(context.Background(), OlderThan, 168*time.Hour, 0))
|
assert.NoError(t, CleanupHookTaskTable(context.Background(), OlderThan, 168*time.Hour, 0))
|
||||||
|
@ -315,14 +315,14 @@ func TestCleanupHookTaskTable_OlderThan_LeavesUndelivered(t *testing.T) {
|
||||||
func TestCleanupHookTaskTable_OlderThan_LeavesTaskEarlierThanAgeToDelete(t *testing.T) {
|
func TestCleanupHookTaskTable_OlderThan_LeavesTaskEarlierThanAgeToDelete(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
hookTask := &HookTask{
|
hookTask := &HookTask{
|
||||||
RepoID: 2,
|
|
||||||
HookID: 4,
|
HookID: 4,
|
||||||
Payloader: &api.PushPayload{},
|
Payloader: &api.PushPayload{},
|
||||||
IsDelivered: true,
|
IsDelivered: true,
|
||||||
Delivered: time.Now().AddDate(0, 0, -6).UnixNano(),
|
Delivered: time.Now().AddDate(0, 0, -6).UnixNano(),
|
||||||
}
|
}
|
||||||
unittest.AssertNotExistsBean(t, hookTask)
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
assert.NoError(t, CreateHookTask(hookTask))
|
_, err := CreateHookTask(db.DefaultContext, hookTask)
|
||||||
|
assert.NoError(t, err)
|
||||||
unittest.AssertExistsAndLoadBean(t, hookTask)
|
unittest.AssertExistsAndLoadBean(t, hookTask)
|
||||||
|
|
||||||
assert.NoError(t, CleanupHookTaskTable(context.Background(), OlderThan, 168*time.Hour, 0))
|
assert.NoError(t, CleanupHookTaskTable(context.Background(), OlderThan, 168*time.Hour, 0))
|
||||||
|
|
|
@ -144,3 +144,39 @@ func IsIcon(node ast.Node) bool {
|
||||||
_, ok := node.(*Icon)
|
_, ok := node.(*Icon)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ColorPreview is an inline for a color preview
|
||||||
|
type ColorPreview struct {
|
||||||
|
ast.BaseInline
|
||||||
|
Color []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dump implements Node.Dump.
|
||||||
|
func (n *ColorPreview) Dump(source []byte, level int) {
|
||||||
|
m := map[string]string{}
|
||||||
|
m["Color"] = string(n.Color)
|
||||||
|
ast.DumpHelper(n, source, level, m, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// KindColorPreview is the NodeKind for ColorPreview
|
||||||
|
var KindColorPreview = ast.NewNodeKind("ColorPreview")
|
||||||
|
|
||||||
|
// Kind implements Node.Kind.
|
||||||
|
func (n *ColorPreview) Kind() ast.NodeKind {
|
||||||
|
return KindColorPreview
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewColorPreview returns a new Span node.
|
||||||
|
func NewColorPreview(color []byte) *ColorPreview {
|
||||||
|
return &ColorPreview{
|
||||||
|
BaseInline: ast.BaseInline{},
|
||||||
|
Color: color,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsColorPreview returns true if the given node implements the ColorPreview interface,
|
||||||
|
// otherwise false.
|
||||||
|
func IsColorPreview(node ast.Node) bool {
|
||||||
|
_, ok := node.(*ColorPreview)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
giteautil "code.gitea.io/gitea/modules/util"
|
giteautil "code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
|
"github.com/microcosm-cc/bluemonday/css"
|
||||||
"github.com/yuin/goldmark/ast"
|
"github.com/yuin/goldmark/ast"
|
||||||
east "github.com/yuin/goldmark/extension/ast"
|
east "github.com/yuin/goldmark/extension/ast"
|
||||||
"github.com/yuin/goldmark/parser"
|
"github.com/yuin/goldmark/parser"
|
||||||
|
@ -178,6 +179,11 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa
|
||||||
v.SetHardLineBreak(setting.Markdown.EnableHardLineBreakInDocuments)
|
v.SetHardLineBreak(setting.Markdown.EnableHardLineBreakInDocuments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case *ast.CodeSpan:
|
||||||
|
colorContent := n.Text(reader.Source())
|
||||||
|
if css.ColorHandler(strings.ToLower(string(colorContent))) {
|
||||||
|
v.AppendChild(v, NewColorPreview(colorContent))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ast.WalkContinue, nil
|
return ast.WalkContinue, nil
|
||||||
})
|
})
|
||||||
|
@ -266,10 +272,43 @@ func (r *HTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
|
||||||
reg.Register(KindDetails, r.renderDetails)
|
reg.Register(KindDetails, r.renderDetails)
|
||||||
reg.Register(KindSummary, r.renderSummary)
|
reg.Register(KindSummary, r.renderSummary)
|
||||||
reg.Register(KindIcon, r.renderIcon)
|
reg.Register(KindIcon, r.renderIcon)
|
||||||
|
reg.Register(ast.KindCodeSpan, r.renderCodeSpan)
|
||||||
reg.Register(KindTaskCheckBoxListItem, r.renderTaskCheckBoxListItem)
|
reg.Register(KindTaskCheckBoxListItem, r.renderTaskCheckBoxListItem)
|
||||||
reg.Register(east.KindTaskCheckBox, r.renderTaskCheckBox)
|
reg.Register(east.KindTaskCheckBox, r.renderTaskCheckBox)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// renderCodeSpan renders CodeSpan elements (like goldmark upstream does) but also renders ColorPreview elements.
|
||||||
|
// See #21474 for reference
|
||||||
|
func (r *HTMLRenderer) renderCodeSpan(w util.BufWriter, source []byte, n ast.Node, entering bool) (ast.WalkStatus, error) {
|
||||||
|
if entering {
|
||||||
|
if n.Attributes() != nil {
|
||||||
|
_, _ = w.WriteString("<code")
|
||||||
|
html.RenderAttributes(w, n, html.CodeAttributeFilter)
|
||||||
|
_ = w.WriteByte('>')
|
||||||
|
} else {
|
||||||
|
_, _ = w.WriteString("<code>")
|
||||||
|
}
|
||||||
|
for c := n.FirstChild(); c != nil; c = c.NextSibling() {
|
||||||
|
switch v := c.(type) {
|
||||||
|
case *ast.Text:
|
||||||
|
segment := v.Segment
|
||||||
|
value := segment.Value(source)
|
||||||
|
if bytes.HasSuffix(value, []byte("\n")) {
|
||||||
|
r.Writer.RawWrite(w, value[:len(value)-1])
|
||||||
|
r.Writer.RawWrite(w, []byte(" "))
|
||||||
|
} else {
|
||||||
|
r.Writer.RawWrite(w, value)
|
||||||
|
}
|
||||||
|
case *ColorPreview:
|
||||||
|
_, _ = w.WriteString(fmt.Sprintf(`<span class="color-preview" style="background-color: %v"></span>`, string(v.Color)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ast.WalkSkipChildren, nil
|
||||||
|
}
|
||||||
|
_, _ = w.WriteString("</code>")
|
||||||
|
return ast.WalkContinue, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *HTMLRenderer) renderDocument(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
|
func (r *HTMLRenderer) renderDocument(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
|
||||||
n := node.(*ast.Document)
|
n := node.(*ast.Document)
|
||||||
|
|
||||||
|
|
|
@ -429,6 +429,61 @@ func TestRenderEmojiInLinks_Issue12331(t *testing.T) {
|
||||||
assert.Equal(t, expected, res)
|
assert.Equal(t, expected, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestColorPreview(t *testing.T) {
|
||||||
|
const nl = "\n"
|
||||||
|
positiveTests := []struct {
|
||||||
|
testcase string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{ // hex
|
||||||
|
"`#FF0000`",
|
||||||
|
`<p><code>#FF0000<span class="color-preview" style="background-color: #FF0000"></span></code></p>` + nl,
|
||||||
|
},
|
||||||
|
{ // rgb
|
||||||
|
"`rgb(16, 32, 64)`",
|
||||||
|
`<p><code>rgb(16, 32, 64)<span class="color-preview" style="background-color: rgb(16, 32, 64)"></span></code></p>` + nl,
|
||||||
|
},
|
||||||
|
{ // short hex
|
||||||
|
"This is the color white `#000`",
|
||||||
|
`<p>This is the color white <code>#000<span class="color-preview" style="background-color: #000"></span></code></p>` + nl,
|
||||||
|
},
|
||||||
|
{ // hsl
|
||||||
|
"HSL stands for hue, saturation, and lightness. An example: `hsl(0, 100%, 50%)`.",
|
||||||
|
`<p>HSL stands for hue, saturation, and lightness. An example: <code>hsl(0, 100%, 50%)<span class="color-preview" style="background-color: hsl(0, 100%, 50%)"></span></code>.</p>` + nl,
|
||||||
|
},
|
||||||
|
{ // uppercase hsl
|
||||||
|
"HSL stands for hue, saturation, and lightness. An example: `HSL(0, 100%, 50%)`.",
|
||||||
|
`<p>HSL stands for hue, saturation, and lightness. An example: <code>HSL(0, 100%, 50%)<span class="color-preview" style="background-color: HSL(0, 100%, 50%)"></span></code>.</p>` + nl,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range positiveTests {
|
||||||
|
res, err := RenderString(&markup.RenderContext{}, test.testcase)
|
||||||
|
assert.NoError(t, err, "Unexpected error in testcase: %q", test.testcase)
|
||||||
|
assert.Equal(t, test.expected, res, "Unexpected result in testcase %q", test.testcase)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
negativeTests := []string{
|
||||||
|
// not a color code
|
||||||
|
"`FF0000`",
|
||||||
|
// inside a code block
|
||||||
|
"```javascript" + nl + `const red = "#FF0000";` + nl + "```",
|
||||||
|
// no backticks
|
||||||
|
"rgb(166, 32, 64)",
|
||||||
|
// typo
|
||||||
|
"`hsI(0, 100%, 50%)`",
|
||||||
|
// looks like a color but not really
|
||||||
|
"`hsl(40, 60, 80)`",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range negativeTests {
|
||||||
|
res, err := RenderString(&markup.RenderContext{}, test)
|
||||||
|
assert.NoError(t, err, "Unexpected error in testcase: %q", test)
|
||||||
|
assert.NotContains(t, res, `<span class="color-preview" style="background-color: `, "Unexpected result in testcase %q", test)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMathBlock(t *testing.T) {
|
func TestMathBlock(t *testing.T) {
|
||||||
const nl = "\n"
|
const nl = "\n"
|
||||||
testcases := []struct {
|
testcases := []struct {
|
||||||
|
|
|
@ -10,8 +10,6 @@ import (
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
|
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -99,8 +97,6 @@ func ExtractMetadataBytes(contents []byte, out interface{}) ([]byte, error) {
|
||||||
return contents, errors.New("could not determine metadata")
|
return contents, errors.New("could not determine metadata")
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("%s", string(front))
|
|
||||||
|
|
||||||
if err := yaml.Unmarshal(front, out); err != nil {
|
if err := yaml.Unmarshal(front, out); err != nil {
|
||||||
return contents, err
|
return contents, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,9 @@ func createDefaultPolicy() *bluemonday.Policy {
|
||||||
// For JS code copy and Mermaid loading state
|
// For JS code copy and Mermaid loading state
|
||||||
policy.AllowAttrs("class").Matching(regexp.MustCompile(`^code-block( is-loading)?$`)).OnElements("pre")
|
policy.AllowAttrs("class").Matching(regexp.MustCompile(`^code-block( is-loading)?$`)).OnElements("pre")
|
||||||
|
|
||||||
|
// For color preview
|
||||||
|
policy.AllowAttrs("class").Matching(regexp.MustCompile(`^color-preview$`)).OnElements("span")
|
||||||
|
|
||||||
// For Chroma markdown plugin
|
// For Chroma markdown plugin
|
||||||
policy.AllowAttrs("class").Matching(regexp.MustCompile(`^(chroma )?language-[\w-]+( display)?( is-loading)?$`)).OnElements("code")
|
policy.AllowAttrs("class").Matching(regexp.MustCompile(`^(chroma )?language-[\w-]+( display)?( is-loading)?$`)).OnElements("code")
|
||||||
|
|
||||||
|
@ -88,8 +91,8 @@ func createDefaultPolicy() *bluemonday.Policy {
|
||||||
// Allow 'style' attribute on text elements.
|
// Allow 'style' attribute on text elements.
|
||||||
policy.AllowAttrs("style").OnElements("span", "p")
|
policy.AllowAttrs("style").OnElements("span", "p")
|
||||||
|
|
||||||
// Allow 'color' property for the style attribute on text elements.
|
// Allow 'color' and 'background-color' properties for the style attribute on text elements.
|
||||||
policy.AllowStyles("color").OnElements("span", "p")
|
policy.AllowStyles("color", "background-color").OnElements("span", "p")
|
||||||
|
|
||||||
// Allow generally safe attributes
|
// Allow generally safe attributes
|
||||||
generalSafeAttrs := []string{
|
generalSafeAttrs := []string{
|
||||||
|
|
|
@ -61,7 +61,7 @@ func (m *webhookNotifier) NotifyIssueClearLabels(doer *user_model.User, issue *i
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = webhook_services.PrepareWebhooks(issue.Repo, webhook.HookEventPullRequestLabel, &api.PullRequestPayload{
|
err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventPullRequestLabel, &api.PullRequestPayload{
|
||||||
Action: api.HookIssueLabelCleared,
|
Action: api.HookIssueLabelCleared,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
|
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
|
||||||
|
@ -69,7 +69,7 @@ func (m *webhookNotifier) NotifyIssueClearLabels(doer *user_model.User, issue *i
|
||||||
Sender: convert.ToUser(doer, nil),
|
Sender: convert.ToUser(doer, nil),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
err = webhook_services.PrepareWebhooks(issue.Repo, webhook.HookEventIssueLabel, &api.IssuePayload{
|
err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventIssueLabel, &api.IssuePayload{
|
||||||
Action: api.HookIssueLabelCleared,
|
Action: api.HookIssueLabelCleared,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
Issue: convert.ToAPIIssue(issue),
|
Issue: convert.ToAPIIssue(issue),
|
||||||
|
@ -87,7 +87,7 @@ func (m *webhookNotifier) NotifyForkRepository(doer *user_model.User, oldRepo, r
|
||||||
mode, _ := access_model.AccessLevel(doer, repo)
|
mode, _ := access_model.AccessLevel(doer, repo)
|
||||||
|
|
||||||
// forked webhook
|
// forked webhook
|
||||||
if err := webhook_services.PrepareWebhooks(oldRepo, webhook.HookEventFork, &api.ForkPayload{
|
if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: oldRepo}, webhook.HookEventFork, &api.ForkPayload{
|
||||||
Forkee: convert.ToRepo(oldRepo, oldMode),
|
Forkee: convert.ToRepo(oldRepo, oldMode),
|
||||||
Repo: convert.ToRepo(repo, mode),
|
Repo: convert.ToRepo(repo, mode),
|
||||||
Sender: convert.ToUser(doer, nil),
|
Sender: convert.ToUser(doer, nil),
|
||||||
|
@ -99,7 +99,7 @@ func (m *webhookNotifier) NotifyForkRepository(doer *user_model.User, oldRepo, r
|
||||||
|
|
||||||
// Add to hook queue for created repo after session commit.
|
// Add to hook queue for created repo after session commit.
|
||||||
if u.IsOrganization() {
|
if u.IsOrganization() {
|
||||||
if err := webhook_services.PrepareWebhooks(repo, webhook.HookEventRepository, &api.RepositoryPayload{
|
if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventRepository, &api.RepositoryPayload{
|
||||||
Action: api.HookRepoCreated,
|
Action: api.HookRepoCreated,
|
||||||
Repository: convert.ToRepo(repo, perm.AccessModeOwner),
|
Repository: convert.ToRepo(repo, perm.AccessModeOwner),
|
||||||
Organization: convert.ToUser(u, nil),
|
Organization: convert.ToUser(u, nil),
|
||||||
|
@ -112,7 +112,7 @@ func (m *webhookNotifier) NotifyForkRepository(doer *user_model.User, oldRepo, r
|
||||||
|
|
||||||
func (m *webhookNotifier) NotifyCreateRepository(doer, u *user_model.User, repo *repo_model.Repository) {
|
func (m *webhookNotifier) NotifyCreateRepository(doer, u *user_model.User, repo *repo_model.Repository) {
|
||||||
// Add to hook queue for created repo after session commit.
|
// Add to hook queue for created repo after session commit.
|
||||||
if err := webhook_services.PrepareWebhooks(repo, webhook.HookEventRepository, &api.RepositoryPayload{
|
if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventRepository, &api.RepositoryPayload{
|
||||||
Action: api.HookRepoCreated,
|
Action: api.HookRepoCreated,
|
||||||
Repository: convert.ToRepo(repo, perm.AccessModeOwner),
|
Repository: convert.ToRepo(repo, perm.AccessModeOwner),
|
||||||
Organization: convert.ToUser(u, nil),
|
Organization: convert.ToUser(u, nil),
|
||||||
|
@ -125,7 +125,7 @@ func (m *webhookNotifier) NotifyCreateRepository(doer, u *user_model.User, repo
|
||||||
func (m *webhookNotifier) NotifyDeleteRepository(doer *user_model.User, repo *repo_model.Repository) {
|
func (m *webhookNotifier) NotifyDeleteRepository(doer *user_model.User, repo *repo_model.Repository) {
|
||||||
u := repo.MustOwner()
|
u := repo.MustOwner()
|
||||||
|
|
||||||
if err := webhook_services.PrepareWebhooks(repo, webhook.HookEventRepository, &api.RepositoryPayload{
|
if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventRepository, &api.RepositoryPayload{
|
||||||
Action: api.HookRepoDeleted,
|
Action: api.HookRepoDeleted,
|
||||||
Repository: convert.ToRepo(repo, perm.AccessModeOwner),
|
Repository: convert.ToRepo(repo, perm.AccessModeOwner),
|
||||||
Organization: convert.ToUser(u, nil),
|
Organization: convert.ToUser(u, nil),
|
||||||
|
@ -137,7 +137,7 @@ func (m *webhookNotifier) NotifyDeleteRepository(doer *user_model.User, repo *re
|
||||||
|
|
||||||
func (m *webhookNotifier) NotifyMigrateRepository(doer, u *user_model.User, repo *repo_model.Repository) {
|
func (m *webhookNotifier) NotifyMigrateRepository(doer, u *user_model.User, repo *repo_model.Repository) {
|
||||||
// Add to hook queue for created repo after session commit.
|
// Add to hook queue for created repo after session commit.
|
||||||
if err := webhook_services.PrepareWebhooks(repo, webhook.HookEventRepository, &api.RepositoryPayload{
|
if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventRepository, &api.RepositoryPayload{
|
||||||
Action: api.HookRepoCreated,
|
Action: api.HookRepoCreated,
|
||||||
Repository: convert.ToRepo(repo, perm.AccessModeOwner),
|
Repository: convert.ToRepo(repo, perm.AccessModeOwner),
|
||||||
Organization: convert.ToUser(u, nil),
|
Organization: convert.ToUser(u, nil),
|
||||||
|
@ -171,7 +171,7 @@ func (m *webhookNotifier) NotifyIssueChangeAssignee(doer *user_model.User, issue
|
||||||
apiPullRequest.Action = api.HookIssueAssigned
|
apiPullRequest.Action = api.HookIssueAssigned
|
||||||
}
|
}
|
||||||
// Assignee comment triggers a webhook
|
// Assignee comment triggers a webhook
|
||||||
if err := webhook_services.PrepareWebhooks(issue.Repo, webhook.HookEventPullRequestAssign, apiPullRequest); err != nil {
|
if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventPullRequestAssign, apiPullRequest); err != nil {
|
||||||
log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err)
|
log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -189,7 +189,7 @@ func (m *webhookNotifier) NotifyIssueChangeAssignee(doer *user_model.User, issue
|
||||||
apiIssue.Action = api.HookIssueAssigned
|
apiIssue.Action = api.HookIssueAssigned
|
||||||
}
|
}
|
||||||
// Assignee comment triggers a webhook
|
// Assignee comment triggers a webhook
|
||||||
if err := webhook_services.PrepareWebhooks(issue.Repo, webhook.HookEventIssueAssign, apiIssue); err != nil {
|
if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventIssueAssign, apiIssue); err != nil {
|
||||||
log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err)
|
log.Error("PrepareWebhooks [is_pull: %v, remove_assignee: %v]: %v", issue.IsPull, removed, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -208,7 +208,7 @@ func (m *webhookNotifier) NotifyIssueChangeTitle(doer *user_model.User, issue *i
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
issue.PullRequest.Issue = issue
|
issue.PullRequest.Issue = issue
|
||||||
err = webhook_services.PrepareWebhooks(issue.Repo, webhook.HookEventPullRequest, &api.PullRequestPayload{
|
err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventPullRequest, &api.PullRequestPayload{
|
||||||
Action: api.HookIssueEdited,
|
Action: api.HookIssueEdited,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
Changes: &api.ChangesPayload{
|
Changes: &api.ChangesPayload{
|
||||||
|
@ -221,7 +221,7 @@ func (m *webhookNotifier) NotifyIssueChangeTitle(doer *user_model.User, issue *i
|
||||||
Sender: convert.ToUser(doer, nil),
|
Sender: convert.ToUser(doer, nil),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
err = webhook_services.PrepareWebhooks(issue.Repo, webhook.HookEventIssues, &api.IssuePayload{
|
err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventIssues, &api.IssuePayload{
|
||||||
Action: api.HookIssueEdited,
|
Action: api.HookIssueEdited,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
Changes: &api.ChangesPayload{
|
Changes: &api.ChangesPayload{
|
||||||
|
@ -263,7 +263,7 @@ func (m *webhookNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue *
|
||||||
} else {
|
} else {
|
||||||
apiPullRequest.Action = api.HookIssueReOpened
|
apiPullRequest.Action = api.HookIssueReOpened
|
||||||
}
|
}
|
||||||
err = webhook_services.PrepareWebhooks(issue.Repo, webhook.HookEventPullRequest, apiPullRequest)
|
err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventPullRequest, apiPullRequest)
|
||||||
} else {
|
} else {
|
||||||
apiIssue := &api.IssuePayload{
|
apiIssue := &api.IssuePayload{
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
|
@ -276,7 +276,7 @@ func (m *webhookNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue *
|
||||||
} else {
|
} else {
|
||||||
apiIssue.Action = api.HookIssueReOpened
|
apiIssue.Action = api.HookIssueReOpened
|
||||||
}
|
}
|
||||||
err = webhook_services.PrepareWebhooks(issue.Repo, webhook.HookEventIssues, apiIssue)
|
err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventIssues, apiIssue)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("PrepareWebhooks [is_pull: %v, is_closed: %v]: %v", issue.IsPull, isClosed, err)
|
log.Error("PrepareWebhooks [is_pull: %v, is_closed: %v]: %v", issue.IsPull, isClosed, err)
|
||||||
|
@ -294,7 +294,7 @@ func (m *webhookNotifier) NotifyNewIssue(issue *issues_model.Issue, mentions []*
|
||||||
}
|
}
|
||||||
|
|
||||||
mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo)
|
mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo)
|
||||||
if err := webhook_services.PrepareWebhooks(issue.Repo, webhook.HookEventIssues, &api.IssuePayload{
|
if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventIssues, &api.IssuePayload{
|
||||||
Action: api.HookIssueOpened,
|
Action: api.HookIssueOpened,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
Issue: convert.ToAPIIssue(issue),
|
Issue: convert.ToAPIIssue(issue),
|
||||||
|
@ -323,7 +323,7 @@ func (m *webhookNotifier) NotifyNewPullRequest(pull *issues_model.PullRequest, m
|
||||||
}
|
}
|
||||||
|
|
||||||
mode, _ := access_model.AccessLevel(pull.Issue.Poster, pull.Issue.Repo)
|
mode, _ := access_model.AccessLevel(pull.Issue.Poster, pull.Issue.Repo)
|
||||||
if err := webhook_services.PrepareWebhooks(pull.Issue.Repo, webhook.HookEventPullRequest, &api.PullRequestPayload{
|
if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: pull.Issue.Repo}, webhook.HookEventPullRequest, &api.PullRequestPayload{
|
||||||
Action: api.HookIssueOpened,
|
Action: api.HookIssueOpened,
|
||||||
Index: pull.Issue.Index,
|
Index: pull.Issue.Index,
|
||||||
PullRequest: convert.ToAPIPullRequest(ctx, pull, nil),
|
PullRequest: convert.ToAPIPullRequest(ctx, pull, nil),
|
||||||
|
@ -342,7 +342,7 @@ func (m *webhookNotifier) NotifyIssueChangeContent(doer *user_model.User, issue
|
||||||
var err error
|
var err error
|
||||||
if issue.IsPull {
|
if issue.IsPull {
|
||||||
issue.PullRequest.Issue = issue
|
issue.PullRequest.Issue = issue
|
||||||
err = webhook_services.PrepareWebhooks(issue.Repo, webhook.HookEventPullRequest, &api.PullRequestPayload{
|
err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventPullRequest, &api.PullRequestPayload{
|
||||||
Action: api.HookIssueEdited,
|
Action: api.HookIssueEdited,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
Changes: &api.ChangesPayload{
|
Changes: &api.ChangesPayload{
|
||||||
|
@ -355,7 +355,7 @@ func (m *webhookNotifier) NotifyIssueChangeContent(doer *user_model.User, issue
|
||||||
Sender: convert.ToUser(doer, nil),
|
Sender: convert.ToUser(doer, nil),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
err = webhook_services.PrepareWebhooks(issue.Repo, webhook.HookEventIssues, &api.IssuePayload{
|
err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventIssues, &api.IssuePayload{
|
||||||
Action: api.HookIssueEdited,
|
Action: api.HookIssueEdited,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
Changes: &api.ChangesPayload{
|
Changes: &api.ChangesPayload{
|
||||||
|
@ -374,54 +374,41 @@ func (m *webhookNotifier) NotifyIssueChangeContent(doer *user_model.User, issue
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *webhookNotifier) NotifyUpdateComment(doer *user_model.User, c *issues_model.Comment, oldContent string) {
|
func (m *webhookNotifier) NotifyUpdateComment(doer *user_model.User, c *issues_model.Comment, oldContent string) {
|
||||||
var err error
|
if err := c.LoadPoster(); err != nil {
|
||||||
|
|
||||||
if err = c.LoadPoster(); err != nil {
|
|
||||||
log.Error("LoadPoster: %v", err)
|
log.Error("LoadPoster: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = c.LoadIssue(); err != nil {
|
if err := c.LoadIssue(); err != nil {
|
||||||
log.Error("LoadIssue: %v", err)
|
log.Error("LoadIssue: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = c.Issue.LoadAttributes(db.DefaultContext); err != nil {
|
if err := c.Issue.LoadAttributes(db.DefaultContext); err != nil {
|
||||||
log.Error("LoadAttributes: %v", err)
|
log.Error("LoadAttributes: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
mode, _ := access_model.AccessLevel(doer, c.Issue.Repo)
|
var eventType webhook.HookEventType
|
||||||
if c.Issue.IsPull {
|
if c.Issue.IsPull {
|
||||||
err = webhook_services.PrepareWebhooks(c.Issue.Repo, webhook.HookEventPullRequestComment, &api.IssueCommentPayload{
|
eventType = webhook.HookEventPullRequestComment
|
||||||
Action: api.HookIssueCommentEdited,
|
|
||||||
Issue: convert.ToAPIIssue(c.Issue),
|
|
||||||
Comment: convert.ToComment(c),
|
|
||||||
Changes: &api.ChangesPayload{
|
|
||||||
Body: &api.ChangesFromPayload{
|
|
||||||
From: oldContent,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Repository: convert.ToRepo(c.Issue.Repo, mode),
|
|
||||||
Sender: convert.ToUser(doer, nil),
|
|
||||||
IsPull: true,
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
err = webhook_services.PrepareWebhooks(c.Issue.Repo, webhook.HookEventIssueComment, &api.IssueCommentPayload{
|
eventType = webhook.HookEventIssueComment
|
||||||
Action: api.HookIssueCommentEdited,
|
|
||||||
Issue: convert.ToAPIIssue(c.Issue),
|
|
||||||
Comment: convert.ToComment(c),
|
|
||||||
Changes: &api.ChangesPayload{
|
|
||||||
Body: &api.ChangesFromPayload{
|
|
||||||
From: oldContent,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Repository: convert.ToRepo(c.Issue.Repo, mode),
|
|
||||||
Sender: convert.ToUser(doer, nil),
|
|
||||||
IsPull: false,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
mode, _ := access_model.AccessLevel(doer, c.Issue.Repo)
|
||||||
|
if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: c.Issue.Repo}, eventType, &api.IssueCommentPayload{
|
||||||
|
Action: api.HookIssueCommentEdited,
|
||||||
|
Issue: convert.ToAPIIssue(c.Issue),
|
||||||
|
Comment: convert.ToComment(c),
|
||||||
|
Changes: &api.ChangesPayload{
|
||||||
|
Body: &api.ChangesFromPayload{
|
||||||
|
From: oldContent,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Repository: convert.ToRepo(c.Issue.Repo, mode),
|
||||||
|
Sender: convert.ToUser(doer, nil),
|
||||||
|
IsPull: c.Issue.IsPull,
|
||||||
|
}); err != nil {
|
||||||
log.Error("PrepareWebhooks [comment_id: %d]: %v", c.ID, err)
|
log.Error("PrepareWebhooks [comment_id: %d]: %v", c.ID, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -429,30 +416,22 @@ func (m *webhookNotifier) NotifyUpdateComment(doer *user_model.User, c *issues_m
|
||||||
func (m *webhookNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository,
|
func (m *webhookNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository,
|
||||||
issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User,
|
issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User,
|
||||||
) {
|
) {
|
||||||
mode, _ := access_model.AccessLevel(doer, repo)
|
var eventType webhook.HookEventType
|
||||||
|
|
||||||
var err error
|
|
||||||
if issue.IsPull {
|
if issue.IsPull {
|
||||||
err = webhook_services.PrepareWebhooks(issue.Repo, webhook.HookEventPullRequestComment, &api.IssueCommentPayload{
|
eventType = webhook.HookEventPullRequestComment
|
||||||
Action: api.HookIssueCommentCreated,
|
|
||||||
Issue: convert.ToAPIIssue(issue),
|
|
||||||
Comment: convert.ToComment(comment),
|
|
||||||
Repository: convert.ToRepo(repo, mode),
|
|
||||||
Sender: convert.ToUser(doer, nil),
|
|
||||||
IsPull: true,
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
err = webhook_services.PrepareWebhooks(issue.Repo, webhook.HookEventIssueComment, &api.IssueCommentPayload{
|
eventType = webhook.HookEventIssueComment
|
||||||
Action: api.HookIssueCommentCreated,
|
|
||||||
Issue: convert.ToAPIIssue(issue),
|
|
||||||
Comment: convert.ToComment(comment),
|
|
||||||
Repository: convert.ToRepo(repo, mode),
|
|
||||||
Sender: convert.ToUser(doer, nil),
|
|
||||||
IsPull: false,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
mode, _ := access_model.AccessLevel(doer, repo)
|
||||||
|
if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: issue.Repo}, eventType, &api.IssueCommentPayload{
|
||||||
|
Action: api.HookIssueCommentCreated,
|
||||||
|
Issue: convert.ToAPIIssue(issue),
|
||||||
|
Comment: convert.ToComment(comment),
|
||||||
|
Repository: convert.ToRepo(repo, mode),
|
||||||
|
Sender: convert.ToUser(doer, nil),
|
||||||
|
IsPull: issue.IsPull,
|
||||||
|
}); err != nil {
|
||||||
log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
|
log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -474,36 +453,29 @@ func (m *webhookNotifier) NotifyDeleteComment(doer *user_model.User, comment *is
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
mode, _ := access_model.AccessLevel(doer, comment.Issue.Repo)
|
var eventType webhook.HookEventType
|
||||||
|
|
||||||
if comment.Issue.IsPull {
|
if comment.Issue.IsPull {
|
||||||
err = webhook_services.PrepareWebhooks(comment.Issue.Repo, webhook.HookEventPullRequestComment, &api.IssueCommentPayload{
|
eventType = webhook.HookEventPullRequestComment
|
||||||
Action: api.HookIssueCommentDeleted,
|
|
||||||
Issue: convert.ToAPIIssue(comment.Issue),
|
|
||||||
Comment: convert.ToComment(comment),
|
|
||||||
Repository: convert.ToRepo(comment.Issue.Repo, mode),
|
|
||||||
Sender: convert.ToUser(doer, nil),
|
|
||||||
IsPull: true,
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
err = webhook_services.PrepareWebhooks(comment.Issue.Repo, webhook.HookEventIssueComment, &api.IssueCommentPayload{
|
eventType = webhook.HookEventIssueComment
|
||||||
Action: api.HookIssueCommentDeleted,
|
|
||||||
Issue: convert.ToAPIIssue(comment.Issue),
|
|
||||||
Comment: convert.ToComment(comment),
|
|
||||||
Repository: convert.ToRepo(comment.Issue.Repo, mode),
|
|
||||||
Sender: convert.ToUser(doer, nil),
|
|
||||||
IsPull: false,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
mode, _ := access_model.AccessLevel(doer, comment.Issue.Repo)
|
||||||
|
if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: comment.Issue.Repo}, eventType, &api.IssueCommentPayload{
|
||||||
|
Action: api.HookIssueCommentDeleted,
|
||||||
|
Issue: convert.ToAPIIssue(comment.Issue),
|
||||||
|
Comment: convert.ToComment(comment),
|
||||||
|
Repository: convert.ToRepo(comment.Issue.Repo, mode),
|
||||||
|
Sender: convert.ToUser(doer, nil),
|
||||||
|
IsPull: comment.Issue.IsPull,
|
||||||
|
}); err != nil {
|
||||||
log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
|
log.Error("PrepareWebhooks [comment_id: %d]: %v", comment.ID, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *webhookNotifier) NotifyNewWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) {
|
func (m *webhookNotifier) NotifyNewWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) {
|
||||||
// Add to hook queue for created wiki page.
|
// Add to hook queue for created wiki page.
|
||||||
if err := webhook_services.PrepareWebhooks(repo, webhook.HookEventWiki, &api.WikiPayload{
|
if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventWiki, &api.WikiPayload{
|
||||||
Action: api.HookWikiCreated,
|
Action: api.HookWikiCreated,
|
||||||
Repository: convert.ToRepo(repo, perm.AccessModeOwner),
|
Repository: convert.ToRepo(repo, perm.AccessModeOwner),
|
||||||
Sender: convert.ToUser(doer, nil),
|
Sender: convert.ToUser(doer, nil),
|
||||||
|
@ -516,7 +488,7 @@ func (m *webhookNotifier) NotifyNewWikiPage(doer *user_model.User, repo *repo_mo
|
||||||
|
|
||||||
func (m *webhookNotifier) NotifyEditWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) {
|
func (m *webhookNotifier) NotifyEditWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) {
|
||||||
// Add to hook queue for edit wiki page.
|
// Add to hook queue for edit wiki page.
|
||||||
if err := webhook_services.PrepareWebhooks(repo, webhook.HookEventWiki, &api.WikiPayload{
|
if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventWiki, &api.WikiPayload{
|
||||||
Action: api.HookWikiEdited,
|
Action: api.HookWikiEdited,
|
||||||
Repository: convert.ToRepo(repo, perm.AccessModeOwner),
|
Repository: convert.ToRepo(repo, perm.AccessModeOwner),
|
||||||
Sender: convert.ToUser(doer, nil),
|
Sender: convert.ToUser(doer, nil),
|
||||||
|
@ -529,7 +501,7 @@ func (m *webhookNotifier) NotifyEditWikiPage(doer *user_model.User, repo *repo_m
|
||||||
|
|
||||||
func (m *webhookNotifier) NotifyDeleteWikiPage(doer *user_model.User, repo *repo_model.Repository, page string) {
|
func (m *webhookNotifier) NotifyDeleteWikiPage(doer *user_model.User, repo *repo_model.Repository, page string) {
|
||||||
// Add to hook queue for edit wiki page.
|
// Add to hook queue for edit wiki page.
|
||||||
if err := webhook_services.PrepareWebhooks(repo, webhook.HookEventWiki, &api.WikiPayload{
|
if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventWiki, &api.WikiPayload{
|
||||||
Action: api.HookWikiDeleted,
|
Action: api.HookWikiDeleted,
|
||||||
Repository: convert.ToRepo(repo, perm.AccessModeOwner),
|
Repository: convert.ToRepo(repo, perm.AccessModeOwner),
|
||||||
Sender: convert.ToUser(doer, nil),
|
Sender: convert.ToUser(doer, nil),
|
||||||
|
@ -567,7 +539,7 @@ func (m *webhookNotifier) NotifyIssueChangeLabels(doer *user_model.User, issue *
|
||||||
log.Error("LoadIssue: %v", err)
|
log.Error("LoadIssue: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = webhook_services.PrepareWebhooks(issue.Repo, webhook.HookEventPullRequestLabel, &api.PullRequestPayload{
|
err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventPullRequestLabel, &api.PullRequestPayload{
|
||||||
Action: api.HookIssueLabelUpdated,
|
Action: api.HookIssueLabelUpdated,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
|
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
|
||||||
|
@ -575,7 +547,7 @@ func (m *webhookNotifier) NotifyIssueChangeLabels(doer *user_model.User, issue *
|
||||||
Sender: convert.ToUser(doer, nil),
|
Sender: convert.ToUser(doer, nil),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
err = webhook_services.PrepareWebhooks(issue.Repo, webhook.HookEventIssueLabel, &api.IssuePayload{
|
err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventIssueLabel, &api.IssuePayload{
|
||||||
Action: api.HookIssueLabelUpdated,
|
Action: api.HookIssueLabelUpdated,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
Issue: convert.ToAPIIssue(issue),
|
Issue: convert.ToAPIIssue(issue),
|
||||||
|
@ -612,7 +584,7 @@ func (m *webhookNotifier) NotifyIssueChangeMilestone(doer *user_model.User, issu
|
||||||
log.Error("LoadIssue: %v", err)
|
log.Error("LoadIssue: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = webhook_services.PrepareWebhooks(issue.Repo, webhook.HookEventPullRequestMilestone, &api.PullRequestPayload{
|
err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventPullRequestMilestone, &api.PullRequestPayload{
|
||||||
Action: hookAction,
|
Action: hookAction,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
|
PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil),
|
||||||
|
@ -620,7 +592,7 @@ func (m *webhookNotifier) NotifyIssueChangeMilestone(doer *user_model.User, issu
|
||||||
Sender: convert.ToUser(doer, nil),
|
Sender: convert.ToUser(doer, nil),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
err = webhook_services.PrepareWebhooks(issue.Repo, webhook.HookEventIssueMilestone, &api.IssuePayload{
|
err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventIssueMilestone, &api.IssuePayload{
|
||||||
Action: hookAction,
|
Action: hookAction,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
Issue: convert.ToAPIIssue(issue),
|
Issue: convert.ToAPIIssue(issue),
|
||||||
|
@ -644,7 +616,7 @@ func (m *webhookNotifier) NotifyPushCommits(pusher *user_model.User, repo *repo_
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := webhook_services.PrepareWebhooks(repo, webhook.HookEventPush, &api.PushPayload{
|
if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: repo}, webhook.HookEventPush, &api.PushPayload{
|
||||||
Ref: opts.RefFullName,
|
Ref: opts.RefFullName,
|
||||||
Before: opts.OldCommitID,
|
Before: opts.OldCommitID,
|
||||||
After: opts.NewCommitID,
|
After: opts.NewCommitID,
|
||||||
|
@ -695,7 +667,7 @@ func (*webhookNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doe
|
||||||
Action: api.HookIssueClosed,
|
Action: api.HookIssueClosed,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = webhook_services.PrepareWebhooks(pr.Issue.Repo, webhook.HookEventPullRequest, apiPullRequest)
|
err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: pr.Issue.Repo}, webhook.HookEventPullRequest, apiPullRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("PrepareWebhooks: %v", err)
|
log.Error("PrepareWebhooks: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -717,7 +689,7 @@ func (m *webhookNotifier) NotifyPullRequestChangeTargetBranch(doer *user_model.U
|
||||||
}
|
}
|
||||||
issue.PullRequest.Issue = issue
|
issue.PullRequest.Issue = issue
|
||||||
mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo)
|
mode, _ := access_model.AccessLevel(issue.Poster, issue.Repo)
|
||||||
err = webhook_services.PrepareWebhooks(issue.Repo, webhook.HookEventPullRequest, &api.PullRequestPayload{
|
err = webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: issue.Repo}, webhook.HookEventPullRequest, &api.PullRequestPayload{
|
||||||
Action: api.HookIssueEdited,
|
Action: api.HookIssueEdited,
|
||||||
Index: issue.Index,
|
Index: issue.Index,
|
||||||
Changes: &api.ChangesPayload{
|
Changes: &api.ChangesPayload{
|
||||||
|
@ -764,7 +736,7 @@ func (m *webhookNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest,
|
||||||
log.Error("models.AccessLevel: %v", err)
|
log.Error("models.AccessLevel: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := webhook_services.PrepareWebhooks(review.Issue.Repo, reviewHookType, &api.PullRequestPayload{
|
if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: review.Issue.Repo}, reviewHookType, &api.PullRequestPayload{
|
||||||
Action: api.HookIssueReviewed,
|
Action: api.HookIssueReviewed,
|
||||||
Index: review.Issue.Index,
|
Index: review.Issue.Index,
|
||||||
PullRequest: convert.ToAPIPullRequest(ctx, pr, nil),
|
PullRequest: convert.ToAPIPullRequest(ctx, pr, nil),
|
||||||
|
@ -784,7 +756,7 @@ func (m *webhookNotifier) NotifyCreateRef(pusher *user_model.User, repo *repo_mo
|
||||||
apiRepo := convert.ToRepo(repo, perm.AccessModeNone)
|
apiRepo := convert.ToRepo(repo, perm.AccessModeNone)
|
||||||
refName := git.RefEndName(refFullName)
|
refName := git.RefEndName(refFullName)
|
||||||
|
|
||||||
if err := webhook_services.PrepareWebhooks(repo, webhook.HookEventCreate, &api.CreatePayload{
|
if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventCreate, &api.CreatePayload{
|
||||||
Ref: refName,
|
Ref: refName,
|
||||||
Sha: refID,
|
Sha: refID,
|
||||||
RefType: refType,
|
RefType: refType,
|
||||||
|
@ -808,7 +780,7 @@ func (m *webhookNotifier) NotifyPullRequestSynchronized(doer *user_model.User, p
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := webhook_services.PrepareWebhooks(pr.Issue.Repo, webhook.HookEventPullRequestSync, &api.PullRequestPayload{
|
if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: pr.Issue.Repo}, webhook.HookEventPullRequestSync, &api.PullRequestPayload{
|
||||||
Action: api.HookIssueSynchronized,
|
Action: api.HookIssueSynchronized,
|
||||||
Index: pr.Issue.Index,
|
Index: pr.Issue.Index,
|
||||||
PullRequest: convert.ToAPIPullRequest(ctx, pr, nil),
|
PullRequest: convert.ToAPIPullRequest(ctx, pr, nil),
|
||||||
|
@ -824,7 +796,7 @@ func (m *webhookNotifier) NotifyDeleteRef(pusher *user_model.User, repo *repo_mo
|
||||||
apiRepo := convert.ToRepo(repo, perm.AccessModeNone)
|
apiRepo := convert.ToRepo(repo, perm.AccessModeNone)
|
||||||
refName := git.RefEndName(refFullName)
|
refName := git.RefEndName(refFullName)
|
||||||
|
|
||||||
if err := webhook_services.PrepareWebhooks(repo, webhook.HookEventDelete, &api.DeletePayload{
|
if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: repo}, webhook.HookEventDelete, &api.DeletePayload{
|
||||||
Ref: refName,
|
Ref: refName,
|
||||||
RefType: refType,
|
RefType: refType,
|
||||||
PusherType: api.PusherTypeUser,
|
PusherType: api.PusherTypeUser,
|
||||||
|
@ -842,7 +814,7 @@ func sendReleaseHook(doer *user_model.User, rel *repo_model.Release, action api.
|
||||||
}
|
}
|
||||||
|
|
||||||
mode, _ := access_model.AccessLevel(doer, rel.Repo)
|
mode, _ := access_model.AccessLevel(doer, rel.Repo)
|
||||||
if err := webhook_services.PrepareWebhooks(rel.Repo, webhook.HookEventRelease, &api.ReleasePayload{
|
if err := webhook_services.PrepareWebhooks(db.DefaultContext, webhook_services.EventSource{Repository: rel.Repo}, webhook.HookEventRelease, &api.ReleasePayload{
|
||||||
Action: action,
|
Action: action,
|
||||||
Release: convert.ToRelease(rel),
|
Release: convert.ToRelease(rel),
|
||||||
Repository: convert.ToRepo(rel.Repo, mode),
|
Repository: convert.ToRepo(rel.Repo, mode),
|
||||||
|
@ -875,7 +847,7 @@ func (m *webhookNotifier) NotifySyncPushCommits(pusher *user_model.User, repo *r
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := webhook_services.PrepareWebhooks(repo, webhook.HookEventPush, &api.PushPayload{
|
if err := webhook_services.PrepareWebhooks(ctx, webhook_services.EventSource{Repository: repo}, webhook.HookEventPush, &api.PushPayload{
|
||||||
Ref: opts.RefFullName,
|
Ref: opts.RefFullName,
|
||||||
Before: opts.OldCommitID,
|
Before: opts.OldCommitID,
|
||||||
After: opts.NewCommitID,
|
After: opts.NewCommitID,
|
||||||
|
@ -908,9 +880,9 @@ func (m *webhookNotifier) NotifyPackageDelete(doer *user_model.User, pd *package
|
||||||
}
|
}
|
||||||
|
|
||||||
func notifyPackage(sender *user_model.User, pd *packages_model.PackageDescriptor, action api.HookPackageAction) {
|
func notifyPackage(sender *user_model.User, pd *packages_model.PackageDescriptor, action api.HookPackageAction) {
|
||||||
if pd.Repository == nil {
|
source := webhook_services.EventSource{
|
||||||
// TODO https://github.com/go-gitea/gitea/pull/17940
|
Repository: pd.Repository,
|
||||||
return
|
Owner: pd.Owner,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.notifyPackage Package: %s[%d]", pd.Package.Name, pd.Package.ID))
|
ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.notifyPackage Package: %s[%d]", pd.Package.Name, pd.Package.ID))
|
||||||
|
@ -922,7 +894,7 @@ func notifyPackage(sender *user_model.User, pd *packages_model.PackageDescriptor
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := webhook_services.PrepareWebhooks(pd.Repository, webhook.HookEventPackage, &api.PackagePayload{
|
if err := webhook_services.PrepareWebhooks(ctx, source, webhook.HookEventPackage, &api.PackagePayload{
|
||||||
Action: action,
|
Action: action,
|
||||||
Package: apiPackage,
|
Package: apiPackage,
|
||||||
Sender: convert.ToUser(sender, nil),
|
Sender: convert.ToUser(sender, nil),
|
||||||
|
|
|
@ -459,6 +459,19 @@ func NewFuncMap() []template.FuncMap {
|
||||||
return items
|
return items
|
||||||
},
|
},
|
||||||
"HasPrefix": strings.HasPrefix,
|
"HasPrefix": strings.HasPrefix,
|
||||||
|
"CompareLink": func(baseRepo, repo *repo_model.Repository, branchName string) string {
|
||||||
|
var curBranch string
|
||||||
|
if repo.ID != baseRepo.ID {
|
||||||
|
curBranch += fmt.Sprintf("%s/%s:", url.PathEscape(repo.OwnerName), url.PathEscape(repo.Name))
|
||||||
|
}
|
||||||
|
curBranch += util.PathEscapeSegments(branchName)
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s/compare/%s...%s",
|
||||||
|
baseRepo.Link(),
|
||||||
|
util.PathEscapeSegments(baseRepo.DefaultBranch),
|
||||||
|
curBranch,
|
||||||
|
)
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -261,6 +261,7 @@ register_success=Успешна регистрация
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Да
|
yes=Да
|
||||||
no=Не
|
no=Не
|
||||||
|
|
|
@ -412,6 +412,7 @@ repo.transfer.body=Chcete-li ji přijmout nebo odmítnout, navštivte %s nebo ji
|
||||||
repo.collaborator.added.subject=%s vás přidal do %s
|
repo.collaborator.added.subject=%s vás přidal do %s
|
||||||
repo.collaborator.added.text=Byl jste přidán jako spolupracovník repozitáře:
|
repo.collaborator.added.text=Byl jste přidán jako spolupracovník repozitáře:
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Ano
|
yes=Ano
|
||||||
no=Ne
|
no=Ne
|
||||||
|
|
|
@ -407,6 +407,7 @@ repo.transfer.body=Um es anzunehmen oder abzulehnen, öffne %s, oder ignoriere e
|
||||||
repo.collaborator.added.subject=%s hat dich zu %s hinzugefügt
|
repo.collaborator.added.subject=%s hat dich zu %s hinzugefügt
|
||||||
repo.collaborator.added.text=Du wurdest als Mitarbeiter für folgendes Repository hinzugefügt:
|
repo.collaborator.added.text=Du wurdest als Mitarbeiter für folgendes Repository hinzugefügt:
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Ja
|
yes=Ja
|
||||||
no=Abbrechen
|
no=Abbrechen
|
||||||
|
|
|
@ -409,6 +409,7 @@ repo.transfer.body=Για να το αποδεχτείτε ή να το απορ
|
||||||
repo.collaborator.added.subject=%s σας πρόσθεσε στο %s
|
repo.collaborator.added.subject=%s σας πρόσθεσε στο %s
|
||||||
repo.collaborator.added.text=Έχετε προστεθεί ως συνεργάτης του αποθετηρίου:
|
repo.collaborator.added.text=Έχετε προστεθεί ως συνεργάτης του αποθετηρίου:
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Ναι
|
yes=Ναι
|
||||||
no=Όχι
|
no=Όχι
|
||||||
|
|
|
@ -411,6 +411,7 @@ repo.transfer.body=Para aceptarlo o rechazarlo, visita %s o simplemente ignórel
|
||||||
repo.collaborator.added.subject=%s le añadió en %s
|
repo.collaborator.added.subject=%s le añadió en %s
|
||||||
repo.collaborator.added.text=Has sido añadido como colaborador del repositorio:
|
repo.collaborator.added.text=Has sido añadido como colaborador del repositorio:
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Sí
|
yes=Sí
|
||||||
no=No
|
no=No
|
||||||
|
|
|
@ -379,6 +379,7 @@ repo.transfer.body=برای تایید یا رد آن %s را ببینید یا
|
||||||
repo.collaborator.added.subject=%s شما را به پروژه %s اضافه کرد
|
repo.collaborator.added.subject=%s شما را به پروژه %s اضافه کرد
|
||||||
repo.collaborator.added.text=شما به عنوان مشارکتکننده در این مخزن اضافه شدید:
|
repo.collaborator.added.text=شما به عنوان مشارکتکننده در این مخزن اضافه شدید:
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=بله
|
yes=بله
|
||||||
no=خیر
|
no=خیر
|
||||||
|
|
|
@ -358,6 +358,7 @@ release.download.targz=Lähdekoodi (TAR.GZ)
|
||||||
repo.transfer.to_you=sinä
|
repo.transfer.to_you=sinä
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Kyllä
|
yes=Kyllä
|
||||||
no=Ei
|
no=Ei
|
||||||
|
|
|
@ -412,6 +412,7 @@ repo.transfer.body=Pour l'accepter ou le rejeter, visitez %s ou ignorez-le.
|
||||||
repo.collaborator.added.subject=%s vous a ajouté à %s
|
repo.collaborator.added.subject=%s vous a ajouté à %s
|
||||||
repo.collaborator.added.text=Vous avez été ajouté en tant que collaborateur du dépôt :
|
repo.collaborator.added.text=Vous avez été ajouté en tant que collaborateur du dépôt :
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Oui
|
yes=Oui
|
||||||
no=Non
|
no=Non
|
||||||
|
|
|
@ -291,6 +291,7 @@ register_success=Sikeres regisztráció
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Igen
|
yes=Igen
|
||||||
no=Nem
|
no=Nem
|
||||||
|
|
|
@ -282,6 +282,7 @@ register_success=Pendaftaran berhasil
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Ya
|
yes=Ya
|
||||||
no=Tidak
|
no=Tidak
|
||||||
|
|
|
@ -339,6 +339,7 @@ repo.transfer.body=Til að samþykkja eða hafna því skaltu fara á %s eða hu
|
||||||
repo.collaborator.added.subject=%s bætti þér við í %s
|
repo.collaborator.added.subject=%s bætti þér við í %s
|
||||||
repo.collaborator.added.text=Þér hefur verið bætt við sem aðila hugbúnaðarsafns:
|
repo.collaborator.added.text=Þér hefur verið bætt við sem aðila hugbúnaðarsafns:
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Já
|
yes=Já
|
||||||
no=Nei
|
no=Nei
|
||||||
|
|
|
@ -407,6 +407,7 @@ repo.transfer.body=Per accettare o respingerla visita %s o semplicemente ignorar
|
||||||
repo.collaborator.added.subject=%s ti ha aggiunto a %s
|
repo.collaborator.added.subject=%s ti ha aggiunto a %s
|
||||||
repo.collaborator.added.text=Sei stato aggiunto come collaboratore del repository:
|
repo.collaborator.added.text=Sei stato aggiunto come collaboratore del repository:
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Sì
|
yes=Sì
|
||||||
no=No
|
no=No
|
||||||
|
|
|
@ -412,6 +412,7 @@ repo.transfer.body=承認または拒否するには %s を開きます。 も
|
||||||
repo.collaborator.added.subject=%s が %s にあなたを追加しました
|
repo.collaborator.added.subject=%s が %s にあなたを追加しました
|
||||||
repo.collaborator.added.text=あなたは次のリポジトリの共同作業者に追加されました:
|
repo.collaborator.added.text=あなたは次のリポジトリの共同作業者に追加されました:
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=はい
|
yes=はい
|
||||||
no=いいえ
|
no=いいえ
|
||||||
|
|
|
@ -273,6 +273,7 @@ register_success=등록 완료
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=예
|
yes=예
|
||||||
no=아니오
|
no=아니오
|
||||||
|
|
|
@ -407,6 +407,7 @@ repo.transfer.body=Ja vēlaties to noraidīt vai apstiprināt, tad apmeklējiet
|
||||||
repo.collaborator.added.subject=%s pievienoja Jūs repozitorijam %s
|
repo.collaborator.added.subject=%s pievienoja Jūs repozitorijam %s
|
||||||
repo.collaborator.added.text=Jūs tikāt pievienots kā līdzstrādnieks repozitorijam:
|
repo.collaborator.added.text=Jūs tikāt pievienots kā līdzstrādnieks repozitorijam:
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Jā
|
yes=Jā
|
||||||
no=Nē
|
no=Nē
|
||||||
|
|
|
@ -261,6 +261,7 @@ register_success=രജിസ്ട്രേഷൻ വിജയകരം
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=അതെ
|
yes=അതെ
|
||||||
no=ഇല്ല
|
no=ഇല്ല
|
||||||
|
|
|
@ -407,6 +407,7 @@ repo.transfer.body=Om het te accepteren of afwijzen, bezoek %s of negeer het gew
|
||||||
repo.collaborator.added.subject=%s heeft jou toegevoegd aan %s
|
repo.collaborator.added.subject=%s heeft jou toegevoegd aan %s
|
||||||
repo.collaborator.added.text=U bent toegevoegd als een medewerker van de repository:
|
repo.collaborator.added.text=U bent toegevoegd als een medewerker van de repository:
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Ja
|
yes=Ja
|
||||||
no=Nee
|
no=Nee
|
||||||
|
|
|
@ -392,6 +392,7 @@ repo.transfer.body=Aby zaakceptować lub odrzucić go, odwiedź %s lub po prostu
|
||||||
repo.collaborator.added.subject=%s dodał Cię do %s
|
repo.collaborator.added.subject=%s dodał Cię do %s
|
||||||
repo.collaborator.added.text=Zostałeś dodany jako współtwórca repozytorium:
|
repo.collaborator.added.text=Zostałeś dodany jako współtwórca repozytorium:
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Tak
|
yes=Tak
|
||||||
no=Nie
|
no=Nie
|
||||||
|
|
|
@ -409,6 +409,7 @@ repo.transfer.body=Para o aceitar ou rejeitar visite %s, ou simplesmente o ignor
|
||||||
repo.collaborator.added.subject=%s adicionou você a %s
|
repo.collaborator.added.subject=%s adicionou você a %s
|
||||||
repo.collaborator.added.text=Você foi adicionado como um colaborador do repositório:
|
repo.collaborator.added.text=Você foi adicionado como um colaborador do repositório:
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Sim
|
yes=Sim
|
||||||
no=Não
|
no=Não
|
||||||
|
|
|
@ -412,6 +412,11 @@ repo.transfer.body=Para o aceitar ou rejeitar visite %s, ou ignore-o, simplesmen
|
||||||
repo.collaborator.added.subject=%s adicionou você a %s
|
repo.collaborator.added.subject=%s adicionou você a %s
|
||||||
repo.collaborator.added.text=Foi adicionado(a) como colaborador(a) do repositório:
|
repo.collaborator.added.text=Foi adicionado(a) como colaborador(a) do repositório:
|
||||||
|
|
||||||
|
team_invite.subject=%[1]s fez-lhe um convite para se juntar à organização %[2]s
|
||||||
|
team_invite.text_1=%[1]s fez-lhe um convite para se juntar à equipa %[2]s na organização %[3]s.
|
||||||
|
team_invite.text_2=Clique na ligação seguinte para se juntar à equipa:
|
||||||
|
team_invite.text_3=Nota: Este convite é dirigido a %[1]s. Se não estava à espera deste convite, pode ignorar este email.
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Sim
|
yes=Sim
|
||||||
no=Não
|
no=Não
|
||||||
|
@ -487,6 +492,7 @@ user_not_exist=O utilizador não existe.
|
||||||
team_not_exist=A equipa não existe.
|
team_not_exist=A equipa não existe.
|
||||||
last_org_owner=Não pode remover o último utilizador da equipa 'proprietários'. Tem que haver pelo menos um proprietário numa organização.
|
last_org_owner=Não pode remover o último utilizador da equipa 'proprietários'. Tem que haver pelo menos um proprietário numa organização.
|
||||||
cannot_add_org_to_team=Uma organização não pode ser adicionada como membro de uma equipa.
|
cannot_add_org_to_team=Uma organização não pode ser adicionada como membro de uma equipa.
|
||||||
|
duplicate_invite_to_team=O(A) utilizador(a) já tinha sido convidado(a) para ser membro da equipa.
|
||||||
|
|
||||||
invalid_ssh_key=Não é possível validar a sua chave SSH: %s
|
invalid_ssh_key=Não é possível validar a sua chave SSH: %s
|
||||||
invalid_gpg_key=Não é possível validar a sua chave GPG: %s
|
invalid_gpg_key=Não é possível validar a sua chave GPG: %s
|
||||||
|
@ -2402,6 +2408,8 @@ teams.members=Membros da equipa
|
||||||
teams.update_settings=Modificar configurações
|
teams.update_settings=Modificar configurações
|
||||||
teams.delete_team=Eliminar equipa
|
teams.delete_team=Eliminar equipa
|
||||||
teams.add_team_member=Adicionar membro da equipa
|
teams.add_team_member=Adicionar membro da equipa
|
||||||
|
teams.invite_team_member=Convidar para %s
|
||||||
|
teams.invite_team_member.list=Convites pendentes
|
||||||
teams.delete_team_title=Eliminar equipa
|
teams.delete_team_title=Eliminar equipa
|
||||||
teams.delete_team_desc=Eliminar uma equipa revoga o acesso dos seus membros ao repositório. Quer continuar?
|
teams.delete_team_desc=Eliminar uma equipa revoga o acesso dos seus membros ao repositório. Quer continuar?
|
||||||
teams.delete_team_success=A equipa foi eliminada.
|
teams.delete_team_success=A equipa foi eliminada.
|
||||||
|
@ -2426,6 +2434,9 @@ teams.all_repositories_helper=A equipa tem acesso a todos os repositórios. Esco
|
||||||
teams.all_repositories_read_permission_desc=Esta equipa atribui o acesso de <strong>leitura</strong> a <strong>todos os repositórios</strong>: os seus membros podem ver e clonar os repositórios.
|
teams.all_repositories_read_permission_desc=Esta equipa atribui o acesso de <strong>leitura</strong> a <strong>todos os repositórios</strong>: os seus membros podem ver e clonar os repositórios.
|
||||||
teams.all_repositories_write_permission_desc=Esta equipa atribui o acesso de <strong>escrita</strong> a <strong>todos os repositórios</strong>: os seus membros podem ler de, e enviar para os repositórios.
|
teams.all_repositories_write_permission_desc=Esta equipa atribui o acesso de <strong>escrita</strong> a <strong>todos os repositórios</strong>: os seus membros podem ler de, e enviar para os repositórios.
|
||||||
teams.all_repositories_admin_permission_desc=Esta equipa atribui o acesso de <strong>administração</strong> a <strong>todos os repositórios</strong>: os seus membros podem ler de, enviar para, e adicionar colaboradores aos repositórios.
|
teams.all_repositories_admin_permission_desc=Esta equipa atribui o acesso de <strong>administração</strong> a <strong>todos os repositórios</strong>: os seus membros podem ler de, enviar para, e adicionar colaboradores aos repositórios.
|
||||||
|
teams.invite.title=Foi-lhe feito um convite para se juntar à equipa <strong>%s</strong> na organização<strong>%s</strong>.
|
||||||
|
teams.invite.by=Convidado(a) por %s
|
||||||
|
teams.invite.description=Clique no botão abaixo para se juntar à equipa.
|
||||||
|
|
||||||
[admin]
|
[admin]
|
||||||
dashboard=Painel de controlo
|
dashboard=Painel de controlo
|
||||||
|
|
|
@ -403,6 +403,7 @@ repo.transfer.body=Для того чтобы принять или отклон
|
||||||
repo.collaborator.added.subject=%s добавил вас в %s
|
repo.collaborator.added.subject=%s добавил вас в %s
|
||||||
repo.collaborator.added.text=Вы были добавлены в качестве соавтора репозитория:
|
repo.collaborator.added.text=Вы были добавлены в качестве соавтора репозитория:
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Да
|
yes=Да
|
||||||
no=Нет
|
no=Нет
|
||||||
|
|
|
@ -365,6 +365,7 @@ repo.transfer.body=එය පිළිගැනීමට හෝ ප්රති
|
||||||
repo.collaborator.added.subject=%s ඔබව %s ට එකතු කළා
|
repo.collaborator.added.subject=%s ඔබව %s ට එකතු කළා
|
||||||
repo.collaborator.added.text=ඔබ ගබඩාවේ සහයෝගිතාකරුවෙකු ලෙස එකතු කර ඇත:
|
repo.collaborator.added.text=ඔබ ගබඩාවේ සහයෝගිතාකරුවෙකු ලෙස එකතු කර ඇත:
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=ඔව්
|
yes=ඔව්
|
||||||
no=නැහැ
|
no=නැහැ
|
||||||
|
|
|
@ -409,6 +409,7 @@ repo.transfer.body=Ak to chcete prijať alebo odmietnuť, navštívte %s alebo t
|
||||||
repo.collaborator.added.subject=%s vás pridal do %s
|
repo.collaborator.added.subject=%s vás pridal do %s
|
||||||
repo.collaborator.added.text=Boli ste pridaný ako spolupracovník repozitára:
|
repo.collaborator.added.text=Boli ste pridaný ako spolupracovník repozitára:
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Áno
|
yes=Áno
|
||||||
no=Nie
|
no=Nie
|
||||||
|
|
|
@ -304,6 +304,7 @@ register_success=Registreringen lyckades
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Ja
|
yes=Ja
|
||||||
no=Nej
|
no=Nej
|
||||||
|
|
|
@ -412,6 +412,7 @@ repo.transfer.body=Kabul veya reddetmek için %s ziyaret edin veya görmezden ge
|
||||||
repo.collaborator.added.subject=%s sizi %s ekledi
|
repo.collaborator.added.subject=%s sizi %s ekledi
|
||||||
repo.collaborator.added.text=Bu depo için katkıcı olarak eklendiniz:
|
repo.collaborator.added.text=Bu depo için katkıcı olarak eklendiniz:
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Evet
|
yes=Evet
|
||||||
no=Hayır
|
no=Hayır
|
||||||
|
|
|
@ -382,6 +382,7 @@ repo.transfer.body=Щоб прийняти або відхилити перей
|
||||||
repo.collaborator.added.subject=%s додав вас до %s
|
repo.collaborator.added.subject=%s додав вас до %s
|
||||||
repo.collaborator.added.text=Ви були додані в якості співавтора репозиторію:
|
repo.collaborator.added.text=Ви були додані в якості співавтора репозиторію:
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=Так
|
yes=Так
|
||||||
no=Ні
|
no=Ні
|
||||||
|
|
|
@ -412,6 +412,11 @@ repo.transfer.body=访问 %s 以接受或拒绝转移,亦可忽略此邮件。
|
||||||
repo.collaborator.added.subject=%s 把你添加到了 %s
|
repo.collaborator.added.subject=%s 把你添加到了 %s
|
||||||
repo.collaborator.added.text=您已被添加为代码库的协作者:
|
repo.collaborator.added.text=您已被添加为代码库的协作者:
|
||||||
|
|
||||||
|
team_invite.subject=%[1]s 邀请您加入组织 %[2]s
|
||||||
|
team_invite.text_1=%[1]s 邀请您加入组织 %[3]s 中的团队 %[2]s。
|
||||||
|
team_invite.text_2=请点击下面的链接加入团队:
|
||||||
|
team_invite.text_3=注意:这是发送给 %[1]s 的邀请。如果您未曾收到过此类邀请,请忽略这封电子邮件。
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=确认操作
|
yes=确认操作
|
||||||
no=取消操作
|
no=取消操作
|
||||||
|
@ -487,6 +492,7 @@ user_not_exist=该用户不存在
|
||||||
team_not_exist=团队不存在
|
team_not_exist=团队不存在
|
||||||
last_org_owner=您不能从 "所有者" 团队中删除最后一个用户。组织中必须至少有一个所有者。
|
last_org_owner=您不能从 "所有者" 团队中删除最后一个用户。组织中必须至少有一个所有者。
|
||||||
cannot_add_org_to_team=组织不能被加入到团队中。
|
cannot_add_org_to_team=组织不能被加入到团队中。
|
||||||
|
duplicate_invite_to_team=此用户已被邀请为团队成员。
|
||||||
|
|
||||||
invalid_ssh_key=无法验证您的 SSH 密钥: %s
|
invalid_ssh_key=无法验证您的 SSH 密钥: %s
|
||||||
invalid_gpg_key=无法验证您的 GPG 密钥: %s
|
invalid_gpg_key=无法验证您的 GPG 密钥: %s
|
||||||
|
@ -861,8 +867,8 @@ readme_helper_desc=这是您可以为您的项目撰写完整描述的地方。
|
||||||
auto_init=初始化仓库(添加. gitignore、许可证和自述文件)
|
auto_init=初始化仓库(添加. gitignore、许可证和自述文件)
|
||||||
trust_model_helper=选择签名验证的“信任模型”。可能的选项是:
|
trust_model_helper=选择签名验证的“信任模型”。可能的选项是:
|
||||||
trust_model_helper_collaborator=协作者:信任协作者的签名
|
trust_model_helper_collaborator=协作者:信任协作者的签名
|
||||||
trust_model_helper_committer=提交者:信任匹配提交者的签名
|
trust_model_helper_committer=提交者:信任与提交者相符的签名
|
||||||
trust_model_helper_collaborator_committer=协作者+提交者:信任与提交者匹配的协作者的签名
|
trust_model_helper_collaborator_committer=协作者+提交者:信任协作者同时是提交者的签名
|
||||||
trust_model_helper_default=默认:使用此安装的默认信任模型
|
trust_model_helper_default=默认:使用此安装的默认信任模型
|
||||||
create_repo=创建仓库
|
create_repo=创建仓库
|
||||||
default_branch=默认分支
|
default_branch=默认分支
|
||||||
|
@ -1882,13 +1888,13 @@ settings.trust_model.default=默认信任模型
|
||||||
settings.trust_model.default.desc=为此安装使用默认仓库信任模型。
|
settings.trust_model.default.desc=为此安装使用默认仓库信任模型。
|
||||||
settings.trust_model.collaborator=协作者
|
settings.trust_model.collaborator=协作者
|
||||||
settings.trust_model.collaborator.long=协作者:信任协作者的签名
|
settings.trust_model.collaborator.long=协作者:信任协作者的签名
|
||||||
settings.trust_model.collaborator.desc=此仓库中协作者的有效签名将被标记为“可信” - 不管他们是否是提交者。否则,如果签名匹配了提交者,有效的签名将被标记为“不可信”。
|
settings.trust_model.collaborator.desc=此仓库中协作者的有效签名将被标记为「可信」(无论它们是否是提交者),签名只符合提交者时将标记为「不可信」,都不匹配时标记为「不匹配」。
|
||||||
settings.trust_model.committer=提交者
|
settings.trust_model.committer=提交者
|
||||||
settings.trust_model.committer.long=提交者: 信任与提交者匹配的签名 (匹配GitHub 并强制Gitea签名的提交者将Gitea作为提交者)
|
settings.trust_model.committer.long=提交者: 信任与提交者相符的签名 (此特性类似 GitHub,这会强制采用 Gitea 作为提交者和签名者)
|
||||||
settings.trust_model.committer.desc=有效的签名只有与提交者匹配时才会被标记为“可信”,否则会被标记为“不匹配”。这会强制Gitea成为已签名提交的提交者,而实际提交者在提交中被标记为Co-authored-by: 和Co-committed-by: trailer。默认的Gitea密钥必须与数据库中的一位用户相匹配。
|
settings.trust_model.committer.desc=提交者的有效签名将被标记为「可信」,否则将被标记为「不匹配」。这会强制 Gitea 成为签名者和提交者,实际的提交者将被标记于提交消息结尾处的「Co-Authored-By:」和「Co-Committed-By:」。默认的 Gitea 签名密钥必须匹配数据库中的一个用户密钥。
|
||||||
settings.trust_model.collaboratorcommitter=协作者+提交者
|
settings.trust_model.collaboratorcommitter=协作者+提交者
|
||||||
settings.trust_model.collaboratorcommitter.long=协作者+提交者:信任协作者同时是提交者的签名
|
settings.trust_model.collaboratorcommitter.long=协作者+提交者:信任协作者同时是提交者的签名
|
||||||
settings.trust_model.collaboratorcommitter.desc=如果匹配为提交者,此仓库中协作者的有效签名将被标记为“可信”。否则,如果签名匹配了提交者或者未匹配,有效的签名将被标记为“不可信”。这将强制 Gitea 在签名提交上将实际提交者加上 Co-Authored-By: 和 Co-Committed-By: 。默认的Gitea密钥必须匹配Gitea用户。
|
settings.trust_model.collaboratorcommitter.desc=此仓库中协作者的有效签名在他同时是提交者时将被标记为「可信」,签名只匹配了提交者时将标记为「不可信」,都不匹配时标记为「不匹配」。这会强制 Gitea 成为签名者和提交者,实际的提交者将被标记于提交消息结尾处的「Co-Authored-By:」和「Co-Committed-By:」。默认的 Gitea 签名密钥必须匹配数据库中的一个用户密钥。
|
||||||
settings.wiki_delete=删除百科数据
|
settings.wiki_delete=删除百科数据
|
||||||
settings.wiki_delete_desc=删除仓库百科数据是永久性的,无法撤消。
|
settings.wiki_delete_desc=删除仓库百科数据是永久性的,无法撤消。
|
||||||
settings.wiki_delete_notices_1=- 这将永久删除和禁用 %s 的百科。
|
settings.wiki_delete_notices_1=- 这将永久删除和禁用 %s 的百科。
|
||||||
|
@ -2402,6 +2408,8 @@ teams.members=团队成员
|
||||||
teams.update_settings=更新团队设置
|
teams.update_settings=更新团队设置
|
||||||
teams.delete_team=删除团队
|
teams.delete_team=删除团队
|
||||||
teams.add_team_member=添加团队成员
|
teams.add_team_member=添加团队成员
|
||||||
|
teams.invite_team_member=邀请加入 %s
|
||||||
|
teams.invite_team_member.list=待处理的邀请
|
||||||
teams.delete_team_title=删除团队
|
teams.delete_team_title=删除团队
|
||||||
teams.delete_team_desc=删除一个团队将删除团队成员的访问权限,继续?
|
teams.delete_team_desc=删除一个团队将删除团队成员的访问权限,继续?
|
||||||
teams.delete_team_success=该团队已被删除。
|
teams.delete_team_success=该团队已被删除。
|
||||||
|
@ -2426,6 +2434,9 @@ teams.all_repositories_helper=团队可以访问所有仓库。选择此选项
|
||||||
teams.all_repositories_read_permission_desc=此团队授予<strong>读取</strong><strong>所有仓库</strong>的访问权限: 成员可以查看和克隆仓库。
|
teams.all_repositories_read_permission_desc=此团队授予<strong>读取</strong><strong>所有仓库</strong>的访问权限: 成员可以查看和克隆仓库。
|
||||||
teams.all_repositories_write_permission_desc=此团队授予<strong>修改</strong><strong>所有仓库</strong>的访问权限: 成员可以查看和推送至仓库。
|
teams.all_repositories_write_permission_desc=此团队授予<strong>修改</strong><strong>所有仓库</strong>的访问权限: 成员可以查看和推送至仓库。
|
||||||
teams.all_repositories_admin_permission_desc=该团队拥有 <strong>管理</strong> <strong>所有仓库</strong>的权限:团队成员可以读取、克隆、推送以及添加其它仓库协作者。
|
teams.all_repositories_admin_permission_desc=该团队拥有 <strong>管理</strong> <strong>所有仓库</strong>的权限:团队成员可以读取、克隆、推送以及添加其它仓库协作者。
|
||||||
|
teams.invite.title=您已被邀请加入组织 <strong>%s</strong> 中的团队 <strong>%s</strong>。
|
||||||
|
teams.invite.by=邀请人 %s
|
||||||
|
teams.invite.description=请点击下面的按钮加入团队。
|
||||||
|
|
||||||
[admin]
|
[admin]
|
||||||
dashboard=管理面板
|
dashboard=管理面板
|
||||||
|
|
|
@ -124,6 +124,7 @@ register_success=註冊成功
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=確認操作
|
yes=確認操作
|
||||||
no=取消操作
|
no=取消操作
|
||||||
|
|
|
@ -410,6 +410,7 @@ repo.transfer.body=請造訪 %s 以接受或拒絕轉移,您也可以忽略它
|
||||||
repo.collaborator.added.subject=%s 把您加入到 %s
|
repo.collaborator.added.subject=%s 把您加入到 %s
|
||||||
repo.collaborator.added.text=您已被新增為儲存庫的協作者:
|
repo.collaborator.added.text=您已被新增為儲存庫的協作者:
|
||||||
|
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
yes=是
|
yes=是
|
||||||
no=否
|
no=否
|
||||||
|
|
|
@ -168,7 +168,7 @@ func TestHook(ctx *context.APIContext) {
|
||||||
commit := convert.ToPayloadCommit(ctx.Repo.Repository, ctx.Repo.Commit)
|
commit := convert.ToPayloadCommit(ctx.Repo.Repository, ctx.Repo.Commit)
|
||||||
|
|
||||||
commitID := ctx.Repo.Commit.ID.String()
|
commitID := ctx.Repo.Commit.ID.String()
|
||||||
if err := webhook_service.PrepareWebhook(hook, ctx.Repo.Repository, webhook.HookEventPush, &api.PushPayload{
|
if err := webhook_service.PrepareWebhook(ctx, hook, webhook.HookEventPush, &api.PushPayload{
|
||||||
Ref: ref,
|
Ref: ref,
|
||||||
Before: commitID,
|
Before: commitID,
|
||||||
After: commitID,
|
After: commitID,
|
||||||
|
|
|
@ -28,7 +28,6 @@ func TestTestHook(t *testing.T) {
|
||||||
assert.EqualValues(t, http.StatusNoContent, ctx.Resp.Status())
|
assert.EqualValues(t, http.StatusNoContent, ctx.Resp.Status())
|
||||||
|
|
||||||
unittest.AssertExistsAndLoadBean(t, &webhook.HookTask{
|
unittest.AssertExistsAndLoadBean(t, &webhook.HookTask{
|
||||||
RepoID: 1,
|
|
||||||
HookID: 1,
|
HookID: 1,
|
||||||
}, unittest.Cond("is_delivered=?", false))
|
}, unittest.Cond("is_delivered=?", false))
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,6 +110,18 @@ func Code(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Data["RepoMaps"] = repoMaps
|
ctx.Data["RepoMaps"] = repoMaps
|
||||||
|
|
||||||
|
if len(loadRepoIDs) != len(repoMaps) {
|
||||||
|
// Remove deleted repos from search results
|
||||||
|
cleanedSearchResults := make([]*code_indexer.Result, 0, len(repoMaps))
|
||||||
|
for _, sr := range searchResults {
|
||||||
|
if _, found := repoMaps[sr.RepoID]; found {
|
||||||
|
cleanedSearchResults = append(cleanedSearchResults, sr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
searchResults = cleanedSearchResults
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Data["SearchResults"] = searchResults
|
ctx.Data["SearchResults"] = searchResults
|
||||||
|
|
|
@ -633,7 +633,7 @@ func TestWebhook(ctx *context.Context) {
|
||||||
hookID := ctx.ParamsInt64(":id")
|
hookID := ctx.ParamsInt64(":id")
|
||||||
w, err := webhook.GetWebhookByRepoID(ctx.Repo.Repository.ID, hookID)
|
w, err := webhook.GetWebhookByRepoID(ctx.Repo.Repository.ID, hookID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Flash.Error("GetWebhookByID: " + err.Error())
|
ctx.Flash.Error("GetWebhookByRepoID: " + err.Error())
|
||||||
ctx.Status(http.StatusInternalServerError)
|
ctx.Status(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -679,7 +679,7 @@ func TestWebhook(ctx *context.Context) {
|
||||||
Pusher: apiUser,
|
Pusher: apiUser,
|
||||||
Sender: apiUser,
|
Sender: apiUser,
|
||||||
}
|
}
|
||||||
if err := webhook_service.PrepareWebhook(w, ctx.Repo.Repository, webhook.HookEventPush, p); err != nil {
|
if err := webhook_service.PrepareWebhook(ctx, w, webhook.HookEventPush, p); err != nil {
|
||||||
ctx.Flash.Error("PrepareWebhook: " + err.Error())
|
ctx.Flash.Error("PrepareWebhook: " + err.Error())
|
||||||
ctx.Status(http.StatusInternalServerError)
|
ctx.Status(http.StatusInternalServerError)
|
||||||
} else {
|
} else {
|
||||||
|
@ -697,7 +697,7 @@ func ReplayWebhook(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := webhook_service.ReplayHookTask(w, hookTaskUUID); err != nil {
|
if err := webhook_service.ReplayHookTask(ctx, w, hookTaskUUID); err != nil {
|
||||||
if webhook.IsErrHookTaskNotExist(err) {
|
if webhook.IsErrHookTaskNotExist(err) {
|
||||||
ctx.NotFound("ReplayHookTask", nil)
|
ctx.NotFound("ReplayHookTask", nil)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -591,6 +591,7 @@ func RegisterRoutes(m *web.Route) {
|
||||||
})
|
})
|
||||||
}, func(ctx *context.Context) {
|
}, func(ctx *context.Context) {
|
||||||
ctx.Data["EnableOAuth2"] = setting.OAuth2.Enable
|
ctx.Data["EnableOAuth2"] = setting.OAuth2.Enable
|
||||||
|
ctx.Data["EnablePackages"] = setting.Packages.Enabled
|
||||||
}, adminReq)
|
}, adminReq)
|
||||||
// ***** END: Admin *****
|
// ***** END: Admin *****
|
||||||
|
|
||||||
|
|
|
@ -1235,8 +1235,13 @@ func SyncAndGetUserSpecificDiff(ctx context.Context, userID int64, pull *issues_
|
||||||
}
|
}
|
||||||
|
|
||||||
changedFiles, err := gitRepo.GetFilesChangedBetween(review.CommitSHA, latestCommit)
|
changedFiles, err := gitRepo.GetFilesChangedBetween(review.CommitSHA, latestCommit)
|
||||||
|
// There are way too many possible errors.
|
||||||
|
// Examples are various git errors such as the commit the review was based on was gc'ed and hence doesn't exist anymore as well as unrecoverable errors where we should serve a 500 response
|
||||||
|
// Due to the current architecture and physical limitation of needing to compare explicit error messages, we can only choose one approach without the code getting ugly
|
||||||
|
// For SOME of the errors such as the gc'ed commit, it would be best to mark all files as changed
|
||||||
|
// But as that does not work for all potential errors, we simply mark all files as unchanged and drop the error which always works, even if not as good as possible
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return diff, err
|
log.Error("Could not get changed files between %s and %s for pull request %d in repo with path %s. Assuming no changes. Error: %w", review.CommitSHA, latestCommit, pull.Index, gitRepo.Path, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
filesChangedSinceLastDiff := make(map[string]pull_model.ViewedState)
|
filesChangedSinceLastDiff := make(map[string]pull_model.ViewedState)
|
||||||
|
|
|
@ -23,7 +23,6 @@ import (
|
||||||
"code.gitea.io/gitea/modules/graceful"
|
"code.gitea.io/gitea/modules/graceful"
|
||||||
"code.gitea.io/gitea/modules/hostmatcher"
|
"code.gitea.io/gitea/modules/hostmatcher"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/process"
|
|
||||||
"code.gitea.io/gitea/modules/proxy"
|
"code.gitea.io/gitea/modules/proxy"
|
||||||
"code.gitea.io/gitea/modules/queue"
|
"code.gitea.io/gitea/modules/queue"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
@ -44,7 +43,7 @@ func Deliver(ctx context.Context, t *webhook_model.HookTask) error {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// There was a panic whilst delivering a hook...
|
// There was a panic whilst delivering a hook...
|
||||||
log.Error("PANIC whilst trying to deliver webhook[%d] for repo[%d] to %s Panic: %v\nStacktrace: %s", t.ID, t.RepoID, w.URL, err, log.Stack(2))
|
log.Error("PANIC whilst trying to deliver webhook[%d] to %s Panic: %v\nStacktrace: %s", t.ID, w.URL, err, log.Stack(2))
|
||||||
}()
|
}()
|
||||||
|
|
||||||
t.IsDelivered = true
|
t.IsDelivered = true
|
||||||
|
@ -202,35 +201,6 @@ func Deliver(ctx context.Context, t *webhook_model.HookTask) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// populateDeliverHooks checks and delivers undelivered hooks.
|
|
||||||
func populateDeliverHooks(ctx context.Context) {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
ctx, _, finished := process.GetManager().AddTypedContext(ctx, "Service: DeliverHooks", process.SystemProcessType, true)
|
|
||||||
defer finished()
|
|
||||||
tasks, err := webhook_model.FindUndeliveredHookTasks()
|
|
||||||
if err != nil {
|
|
||||||
log.Error("DeliverHooks: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update hook task status.
|
|
||||||
for _, t := range tasks {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := addToTask(t.RepoID); err != nil {
|
|
||||||
log.Error("DeliverHook failed [%d]: %v", t.RepoID, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
webhookHTTPClient *http.Client
|
webhookHTTPClient *http.Client
|
||||||
once sync.Once
|
once sync.Once
|
||||||
|
@ -281,13 +251,23 @@ func Init() error {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
hookQueue = queue.CreateUniqueQueue("webhook_sender", handle, "")
|
hookQueue = queue.CreateUniqueQueue("webhook_sender", handle, int64(0))
|
||||||
if hookQueue == nil {
|
if hookQueue == nil {
|
||||||
return fmt.Errorf("Unable to create webhook_sender Queue")
|
return fmt.Errorf("Unable to create webhook_sender Queue")
|
||||||
}
|
}
|
||||||
go graceful.GetManager().RunWithShutdownFns(hookQueue.Run)
|
go graceful.GetManager().RunWithShutdownFns(hookQueue.Run)
|
||||||
|
|
||||||
populateDeliverHooks(graceful.GetManager().HammerContext())
|
tasks, err := webhook_model.FindUndeliveredHookTasks(graceful.GetManager().HammerContext())
|
||||||
|
if err != nil {
|
||||||
|
log.Error("FindUndeliveredHookTasks failed: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, task := range tasks {
|
||||||
|
if err := enqueueHookTask(task); err != nil {
|
||||||
|
log.Error("enqueueHookTask failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,10 @@ package webhook
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
webhook_model "code.gitea.io/gitea/models/webhook"
|
webhook_model "code.gitea.io/gitea/models/webhook"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/graceful"
|
"code.gitea.io/gitea/modules/graceful"
|
||||||
|
@ -104,49 +103,38 @@ func getPayloadBranch(p api.Payloader) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle passed PR IDs and test the PRs
|
// EventSource represents the source of a webhook action. Repository and/or Owner must be set.
|
||||||
|
type EventSource struct {
|
||||||
|
Repository *repo_model.Repository
|
||||||
|
Owner *user_model.User
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle delivers hook tasks
|
||||||
func handle(data ...queue.Data) []queue.Data {
|
func handle(data ...queue.Data) []queue.Data {
|
||||||
for _, datum := range data {
|
ctx := graceful.GetManager().HammerContext()
|
||||||
repoIDStr := datum.(string)
|
|
||||||
log.Trace("DeliverHooks [repo_id: %v]", repoIDStr)
|
|
||||||
|
|
||||||
repoID, err := strconv.ParseInt(repoIDStr, 10, 64)
|
for _, taskID := range data {
|
||||||
|
task, err := webhook_model.GetHookTaskByID(ctx, taskID.(int64))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Invalid repo ID: %s", repoIDStr)
|
log.Error("GetHookTaskByID failed: %v", err)
|
||||||
continue
|
} else {
|
||||||
|
if err := Deliver(ctx, task); err != nil {
|
||||||
|
log.Error("webhook.Deliver failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks, err := webhook_model.FindRepoUndeliveredHookTasks(repoID)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("Get repository [%d] hook tasks: %v", repoID, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, t := range tasks {
|
|
||||||
if err = Deliver(graceful.GetManager().HammerContext(), t); err != nil {
|
|
||||||
log.Error("deliver: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addToTask(repoID int64) error {
|
func enqueueHookTask(task *webhook_model.HookTask) error {
|
||||||
err := hookQueue.PushFunc(strconv.FormatInt(repoID, 10), nil)
|
err := hookQueue.PushFunc(task.ID, nil)
|
||||||
if err != nil && err != queue.ErrAlreadyInQueue {
|
if err != nil && err != queue.ErrAlreadyInQueue {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrepareWebhook adds special webhook to task queue for given payload.
|
|
||||||
func PrepareWebhook(w *webhook_model.Webhook, repo *repo_model.Repository, event webhook_model.HookEventType, p api.Payloader) error {
|
|
||||||
if err := prepareWebhook(w, repo, event, p); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return addToTask(repo.ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkBranch(w *webhook_model.Webhook, branch string) bool {
|
func checkBranch(w *webhook_model.Webhook, branch string) bool {
|
||||||
if w.BranchFilter == "" || w.BranchFilter == "*" {
|
if w.BranchFilter == "" || w.BranchFilter == "*" {
|
||||||
return true
|
return true
|
||||||
|
@ -162,7 +150,8 @@ func checkBranch(w *webhook_model.Webhook, branch string) bool {
|
||||||
return g.Match(branch)
|
return g.Match(branch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareWebhook(w *webhook_model.Webhook, repo *repo_model.Repository, event webhook_model.HookEventType, p api.Payloader) error {
|
// PrepareWebhook creates a hook task and enqueues it for processing
|
||||||
|
func PrepareWebhook(ctx context.Context, w *webhook_model.Webhook, event webhook_model.HookEventType, p api.Payloader) error {
|
||||||
// Skip sending if webhooks are disabled.
|
// Skip sending if webhooks are disabled.
|
||||||
if setting.DisableWebhooks {
|
if setting.DisableWebhooks {
|
||||||
return nil
|
return nil
|
||||||
|
@ -207,44 +196,45 @@ func prepareWebhook(w *webhook_model.Webhook, repo *repo_model.Repository, event
|
||||||
payloader = p
|
payloader = p
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = webhook_model.CreateHookTask(&webhook_model.HookTask{
|
task, err := webhook_model.CreateHookTask(ctx, &webhook_model.HookTask{
|
||||||
RepoID: repo.ID,
|
|
||||||
HookID: w.ID,
|
HookID: w.ID,
|
||||||
Payloader: payloader,
|
Payloader: payloader,
|
||||||
EventType: event,
|
EventType: event,
|
||||||
}); err != nil {
|
})
|
||||||
|
if err != nil {
|
||||||
return fmt.Errorf("CreateHookTask: %v", err)
|
return fmt.Errorf("CreateHookTask: %v", err)
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
return enqueueHookTask(task)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrepareWebhooks adds new webhooks to task queue for given payload.
|
// PrepareWebhooks adds new webhooks to task queue for given payload.
|
||||||
func PrepareWebhooks(repo *repo_model.Repository, event webhook_model.HookEventType, p api.Payloader) error {
|
func PrepareWebhooks(ctx context.Context, source EventSource, event webhook_model.HookEventType, p api.Payloader) error {
|
||||||
if err := prepareWebhooks(db.DefaultContext, repo, event, p); err != nil {
|
owner := source.Owner
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return addToTask(repo.ID)
|
var ws []*webhook_model.Webhook
|
||||||
}
|
|
||||||
|
|
||||||
func prepareWebhooks(ctx context.Context, repo *repo_model.Repository, event webhook_model.HookEventType, p api.Payloader) error {
|
if source.Repository != nil {
|
||||||
ws, err := webhook_model.ListWebhooksByOpts(ctx, &webhook_model.ListWebhookOptions{
|
repoHooks, err := webhook_model.ListWebhooksByOpts(ctx, &webhook_model.ListWebhookOptions{
|
||||||
RepoID: repo.ID,
|
RepoID: source.Repository.ID,
|
||||||
IsActive: util.OptionalBoolTrue,
|
IsActive: util.OptionalBoolTrue,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("GetActiveWebhooksByRepoID: %v", err)
|
return fmt.Errorf("ListWebhooksByOpts: %v", err)
|
||||||
|
}
|
||||||
|
ws = append(ws, repoHooks...)
|
||||||
|
|
||||||
|
owner = source.Repository.MustOwner()
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if repo belongs to org and append additional webhooks
|
// check if owner is an org and append additional webhooks
|
||||||
if repo.MustOwner().IsOrganization() {
|
if owner != nil && owner.IsOrganization() {
|
||||||
// get hooks for org
|
|
||||||
orgHooks, err := webhook_model.ListWebhooksByOpts(ctx, &webhook_model.ListWebhookOptions{
|
orgHooks, err := webhook_model.ListWebhooksByOpts(ctx, &webhook_model.ListWebhookOptions{
|
||||||
OrgID: repo.OwnerID,
|
OrgID: owner.ID,
|
||||||
IsActive: util.OptionalBoolTrue,
|
IsActive: util.OptionalBoolTrue,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("GetActiveWebhooksByOrgID: %v", err)
|
return fmt.Errorf("ListWebhooksByOpts: %v", err)
|
||||||
}
|
}
|
||||||
ws = append(ws, orgHooks...)
|
ws = append(ws, orgHooks...)
|
||||||
}
|
}
|
||||||
|
@ -261,7 +251,7 @@ func prepareWebhooks(ctx context.Context, repo *repo_model.Repository, event web
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, w := range ws {
|
for _, w := range ws {
|
||||||
if err = prepareWebhook(w, repo, event, p); err != nil {
|
if err := PrepareWebhook(ctx, w, event, p); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -269,11 +259,11 @@ func prepareWebhooks(ctx context.Context, repo *repo_model.Repository, event web
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReplayHookTask replays a webhook task
|
// ReplayHookTask replays a webhook task
|
||||||
func ReplayHookTask(w *webhook_model.Webhook, uuid string) error {
|
func ReplayHookTask(ctx context.Context, w *webhook_model.Webhook, uuid string) error {
|
||||||
t, err := webhook_model.ReplayHookTask(w.ID, uuid)
|
task, err := webhook_model.ReplayHookTask(ctx, w.ID, uuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return addToTask(t.RepoID)
|
return enqueueHookTask(task)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ package webhook
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
webhook_model "code.gitea.io/gitea/models/webhook"
|
webhook_model "code.gitea.io/gitea/models/webhook"
|
||||||
|
@ -32,12 +33,12 @@ func TestPrepareWebhooks(t *testing.T) {
|
||||||
|
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
hookTasks := []*webhook_model.HookTask{
|
hookTasks := []*webhook_model.HookTask{
|
||||||
{RepoID: repo.ID, HookID: 1, EventType: webhook_model.HookEventPush},
|
{HookID: 1, EventType: webhook_model.HookEventPush},
|
||||||
}
|
}
|
||||||
for _, hookTask := range hookTasks {
|
for _, hookTask := range hookTasks {
|
||||||
unittest.AssertNotExistsBean(t, hookTask)
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
}
|
}
|
||||||
assert.NoError(t, PrepareWebhooks(repo, webhook_model.HookEventPush, &api.PushPayload{Commits: []*api.PayloadCommit{{}}}))
|
assert.NoError(t, PrepareWebhooks(db.DefaultContext, EventSource{Repository: repo}, webhook_model.HookEventPush, &api.PushPayload{Commits: []*api.PayloadCommit{{}}}))
|
||||||
for _, hookTask := range hookTasks {
|
for _, hookTask := range hookTasks {
|
||||||
unittest.AssertExistsAndLoadBean(t, hookTask)
|
unittest.AssertExistsAndLoadBean(t, hookTask)
|
||||||
}
|
}
|
||||||
|
@ -48,13 +49,13 @@ func TestPrepareWebhooksBranchFilterMatch(t *testing.T) {
|
||||||
|
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
||||||
hookTasks := []*webhook_model.HookTask{
|
hookTasks := []*webhook_model.HookTask{
|
||||||
{RepoID: repo.ID, HookID: 4, EventType: webhook_model.HookEventPush},
|
{HookID: 4, EventType: webhook_model.HookEventPush},
|
||||||
}
|
}
|
||||||
for _, hookTask := range hookTasks {
|
for _, hookTask := range hookTasks {
|
||||||
unittest.AssertNotExistsBean(t, hookTask)
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
}
|
}
|
||||||
// this test also ensures that * doesn't handle / in any special way (like shell would)
|
// this test also ensures that * doesn't handle / in any special way (like shell would)
|
||||||
assert.NoError(t, PrepareWebhooks(repo, webhook_model.HookEventPush, &api.PushPayload{Ref: "refs/heads/feature/7791", Commits: []*api.PayloadCommit{{}}}))
|
assert.NoError(t, PrepareWebhooks(db.DefaultContext, EventSource{Repository: repo}, webhook_model.HookEventPush, &api.PushPayload{Ref: "refs/heads/feature/7791", Commits: []*api.PayloadCommit{{}}}))
|
||||||
for _, hookTask := range hookTasks {
|
for _, hookTask := range hookTasks {
|
||||||
unittest.AssertExistsAndLoadBean(t, hookTask)
|
unittest.AssertExistsAndLoadBean(t, hookTask)
|
||||||
}
|
}
|
||||||
|
@ -65,12 +66,12 @@ func TestPrepareWebhooksBranchFilterNoMatch(t *testing.T) {
|
||||||
|
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
||||||
hookTasks := []*webhook_model.HookTask{
|
hookTasks := []*webhook_model.HookTask{
|
||||||
{RepoID: repo.ID, HookID: 4, EventType: webhook_model.HookEventPush},
|
{HookID: 4, EventType: webhook_model.HookEventPush},
|
||||||
}
|
}
|
||||||
for _, hookTask := range hookTasks {
|
for _, hookTask := range hookTasks {
|
||||||
unittest.AssertNotExistsBean(t, hookTask)
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
}
|
}
|
||||||
assert.NoError(t, PrepareWebhooks(repo, webhook_model.HookEventPush, &api.PushPayload{Ref: "refs/heads/fix_weird_bug"}))
|
assert.NoError(t, PrepareWebhooks(db.DefaultContext, EventSource{Repository: repo}, webhook_model.HookEventPush, &api.PushPayload{Ref: "refs/heads/fix_weird_bug"}))
|
||||||
|
|
||||||
for _, hookTask := range hookTasks {
|
for _, hookTask := range hookTasks {
|
||||||
unittest.AssertNotExistsBean(t, hookTask)
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
|
|
|
@ -12,9 +12,11 @@
|
||||||
<a class="{{if .PageIsAdminRepositories}}active{{end}} item" href="{{AppSubUrl}}/admin/repos">
|
<a class="{{if .PageIsAdminRepositories}}active{{end}} item" href="{{AppSubUrl}}/admin/repos">
|
||||||
{{.locale.Tr "admin.repositories"}}
|
{{.locale.Tr "admin.repositories"}}
|
||||||
</a>
|
</a>
|
||||||
|
{{if .EnablePackages}}
|
||||||
<a class="{{if .PageIsAdminPackages}}active{{end}} item" href="{{AppSubUrl}}/admin/packages">
|
<a class="{{if .PageIsAdminPackages}}active{{end}} item" href="{{AppSubUrl}}/admin/packages">
|
||||||
{{.locale.Tr "packages.title"}}
|
{{.locale.Tr "packages.title"}}
|
||||||
</a>
|
</a>
|
||||||
|
{{end}}
|
||||||
{{if not DisableWebhooks}}
|
{{if not DisableWebhooks}}
|
||||||
<a class="{{if or .PageIsAdminDefaultHooks .PageIsAdminSystemHooks}}active{{end}} item" href="{{AppSubUrl}}/admin/hooks">
|
<a class="{{if or .PageIsAdminDefaultHooks .PageIsAdminSystemHooks}}active{{end}} item" href="{{AppSubUrl}}/admin/hooks">
|
||||||
{{.locale.Tr "admin.hooks"}}
|
{{.locale.Tr "admin.hooks"}}
|
||||||
|
|
|
@ -70,7 +70,7 @@
|
||||||
<!-- If home page, show new PR. If not, show breadcrumb -->
|
<!-- If home page, show new PR. If not, show breadcrumb -->
|
||||||
{{if eq $n 0}}
|
{{if eq $n 0}}
|
||||||
{{if and .CanCompareOrPull .IsViewBranch (not .Repository.IsArchived)}}
|
{{if and .CanCompareOrPull .IsViewBranch (not .Repository.IsArchived)}}
|
||||||
<a href="{{.BaseRepo.Link}}/compare/{{PathEscapeSegments .BaseRepo.DefaultBranch}}...{{if ne .Repository.Owner.Name .BaseRepo.Owner.Name}}{{PathEscape .Repository.Owner.Name}}{{if .BaseRepo.IsFork}}/{{PathEscape .Repository.Name}}{{end}}:{{end}}{{PathEscapeSegments .BranchName}}">
|
<a href="{{CompareLink .BaseRepo .Repository .BranchName}}">
|
||||||
<button id="new-pull-request" class="ui compact basic button tooltip" data-content="{{if .PullRequestCtx.Allowed}}{{.locale.Tr "repo.pulls.compare_changes"}}{{else}}{{.locale.Tr "action.compare_branch"}}{{end}}"><span class="text">{{svg "octicon-git-pull-request"}}</span></button>
|
<button id="new-pull-request" class="ui compact basic button tooltip" data-content="{{if .PullRequestCtx.Allowed}}{{.locale.Tr "repo.pulls.compare_changes"}}{{else}}{{.locale.Tr "action.compare_branch"}}{{end}}"><span class="text">{{svg "octicon-git-pull-request"}}</span></button>
|
||||||
</a>
|
</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -263,19 +264,19 @@ var tokenCounter int64
|
||||||
|
|
||||||
func getTokenForLoggedInUser(t testing.TB, session *TestSession) string {
|
func getTokenForLoggedInUser(t testing.TB, session *TestSession) string {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
tokenCounter++
|
|
||||||
req := NewRequest(t, "GET", "/user/settings/applications")
|
req := NewRequest(t, "GET", "/user/settings/applications")
|
||||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
doc := NewHTMLParser(t, resp.Body)
|
doc := NewHTMLParser(t, resp.Body)
|
||||||
req = NewRequestWithValues(t, "POST", "/user/settings/applications", map[string]string{
|
req = NewRequestWithValues(t, "POST", "/user/settings/applications", map[string]string{
|
||||||
"_csrf": doc.GetCSRF(),
|
"_csrf": doc.GetCSRF(),
|
||||||
"name": fmt.Sprintf("api-testing-token-%d", tokenCounter),
|
"name": fmt.Sprintf("api-testing-token-%d", atomic.AddInt64(&tokenCounter, 1)),
|
||||||
})
|
})
|
||||||
session.MakeRequest(t, req, http.StatusSeeOther)
|
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||||
req = NewRequest(t, "GET", "/user/settings/applications")
|
req = NewRequest(t, "GET", "/user/settings/applications")
|
||||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||||
token := htmlDoc.doc.Find(".ui.info p").Text()
|
token := htmlDoc.doc.Find(".ui.info p").Text()
|
||||||
|
assert.NotEmpty(t, token)
|
||||||
return token
|
return token
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1371,6 +1371,14 @@ a.ui.card:hover,
|
||||||
border-color: var(--color-secondary);
|
border-color: var(--color-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.color-preview {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: .4em;
|
||||||
|
height: .67em;
|
||||||
|
width: .67em;
|
||||||
|
border-radius: .15em;
|
||||||
|
}
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
background-color: var(--color-footer);
|
background-color: var(--color-footer);
|
||||||
border-top: 1px solid var(--color-secondary);
|
border-top: 1px solid var(--color-secondary);
|
||||||
|
|
Loading…
Add table
Reference in a new issue