mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	Add new API endpoints for push mirrors management (#19841)
- Add a new push mirror to specific repository - Sync now ( send all the changes to the configured push mirrors ) - Get list of all push mirrors of a repository - Get a push mirror by ID - Delete push mirror by ID Signed-off-by: Mohamed Sekour <mohamed.sekour@exfo.com> Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: zeripath <art27@cantab.net>
This commit is contained in:
		@@ -13,6 +13,7 @@ import (
 | 
				
			|||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/models"
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
 | 
						"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"
 | 
				
			||||||
	user_model "code.gitea.io/gitea/models/user"
 | 
						user_model "code.gitea.io/gitea/models/user"
 | 
				
			||||||
@@ -47,7 +48,7 @@ func testMirrorPush(t *testing.T, u *url.URL) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	doCreatePushMirror(ctx, fmt.Sprintf("%s%s/%s", u.String(), url.PathEscape(ctx.Username), url.PathEscape(mirrorRepo.Name)), user.LowerName, userPassword)(t)
 | 
						doCreatePushMirror(ctx, fmt.Sprintf("%s%s/%s", u.String(), url.PathEscape(ctx.Username), url.PathEscape(mirrorRepo.Name)), user.LowerName, userPassword)(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mirrors, err := repo_model.GetPushMirrorsByRepoID(srcRepo.ID)
 | 
						mirrors, _, err := repo_model.GetPushMirrorsByRepoID(db.DefaultContext, srcRepo.ID, db.ListOptions{})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, mirrors, 1)
 | 
						assert.Len(t, mirrors, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -72,7 +73,7 @@ func testMirrorPush(t *testing.T, u *url.URL) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Cleanup
 | 
						// Cleanup
 | 
				
			||||||
	doRemovePushMirror(ctx, fmt.Sprintf("%s%s/%s", u.String(), url.PathEscape(ctx.Username), url.PathEscape(mirrorRepo.Name)), user.LowerName, userPassword, int(mirrors[0].ID))(t)
 | 
						doRemovePushMirror(ctx, fmt.Sprintf("%s%s/%s", u.String(), url.PathEscape(ctx.Username), url.PathEscape(mirrorRepo.Name)), user.LowerName, userPassword, int(mirrors[0].ID))(t)
 | 
				
			||||||
	mirrors, err = repo_model.GetPushMirrorsByRepoID(srcRepo.ID)
 | 
						mirrors, _, err = repo_model.GetPushMirrorsByRepoID(db.DefaultContext, srcRepo.ID, db.ListOptions{})
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.Len(t, mirrors, 0)
 | 
						assert.Len(t, mirrors, 0)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,12 +5,15 @@
 | 
				
			|||||||
package repo
 | 
					package repo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/models/db"
 | 
						"code.gitea.io/gitea/models/db"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/log"
 | 
						"code.gitea.io/gitea/modules/log"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/timeutil"
 | 
						"code.gitea.io/gitea/modules/timeutil"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"xorm.io/builder"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ErrPushMirrorNotExist mirror does not exist error
 | 
					// ErrPushMirrorNotExist mirror does not exist error
 | 
				
			||||||
@@ -29,6 +32,25 @@ type PushMirror struct {
 | 
				
			|||||||
	LastUpdateUnix timeutil.TimeStamp `xorm:"INDEX last_update"`
 | 
						LastUpdateUnix timeutil.TimeStamp `xorm:"INDEX last_update"`
 | 
				
			||||||
	LastError      string             `xorm:"text"`
 | 
						LastError      string             `xorm:"text"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					type PushMirrorOptions struct {
 | 
				
			||||||
 | 
						ID         int64
 | 
				
			||||||
 | 
						RepoID     int64
 | 
				
			||||||
 | 
						RemoteName string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (opts *PushMirrorOptions) toConds() builder.Cond {
 | 
				
			||||||
 | 
						cond := builder.NewCond()
 | 
				
			||||||
 | 
						if opts.RepoID > 0 {
 | 
				
			||||||
 | 
							cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if opts.RemoteName != "" {
 | 
				
			||||||
 | 
							cond = cond.And(builder.Eq{"remote_name": opts.RemoteName})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if opts.ID > 0 {
 | 
				
			||||||
 | 
							cond = cond.And(builder.Eq{"id": opts.ID})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return cond
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	db.RegisterModel(new(PushMirror))
 | 
						db.RegisterModel(new(PushMirror))
 | 
				
			||||||
@@ -53,45 +75,48 @@ func (m *PushMirror) GetRemoteName() string {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// InsertPushMirror inserts a push-mirror to database
 | 
					// InsertPushMirror inserts a push-mirror to database
 | 
				
			||||||
func InsertPushMirror(m *PushMirror) error {
 | 
					func InsertPushMirror(ctx context.Context, m *PushMirror) error {
 | 
				
			||||||
	_, err := db.GetEngine(db.DefaultContext).Insert(m)
 | 
						_, err := db.GetEngine(ctx).Insert(m)
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UpdatePushMirror updates the push-mirror
 | 
					// UpdatePushMirror updates the push-mirror
 | 
				
			||||||
func UpdatePushMirror(m *PushMirror) error {
 | 
					func UpdatePushMirror(ctx context.Context, m *PushMirror) error {
 | 
				
			||||||
	_, err := db.GetEngine(db.DefaultContext).ID(m.ID).AllCols().Update(m)
 | 
						_, err := db.GetEngine(ctx).ID(m.ID).AllCols().Update(m)
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeletePushMirrorByID deletes a push-mirrors by ID
 | 
					func DeletePushMirrors(ctx context.Context, opts PushMirrorOptions) error {
 | 
				
			||||||
func DeletePushMirrorByID(ID int64) error {
 | 
						if opts.RepoID > 0 {
 | 
				
			||||||
	_, err := db.GetEngine(db.DefaultContext).ID(ID).Delete(&PushMirror{})
 | 
							_, err := db.GetEngine(ctx).Where(opts.toConds()).Delete(&PushMirror{})
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return errors.New("repoID required and must be set")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeletePushMirrorsByRepoID deletes all push-mirrors by repoID
 | 
					func GetPushMirror(ctx context.Context, opts PushMirrorOptions) (*PushMirror, error) {
 | 
				
			||||||
func DeletePushMirrorsByRepoID(repoID int64) error {
 | 
						mirror := &PushMirror{}
 | 
				
			||||||
	_, err := db.GetEngine(db.DefaultContext).Delete(&PushMirror{RepoID: repoID})
 | 
						exist, err := db.GetEngine(ctx).Where(opts.toConds()).Get(mirror)
 | 
				
			||||||
	return err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetPushMirrorByID returns push-mirror information.
 | 
					 | 
				
			||||||
func GetPushMirrorByID(ID int64) (*PushMirror, error) {
 | 
					 | 
				
			||||||
	m := &PushMirror{}
 | 
					 | 
				
			||||||
	has, err := db.GetEngine(db.DefaultContext).ID(ID).Get(m)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	} else if !has {
 | 
						} else if !exist {
 | 
				
			||||||
		return nil, ErrPushMirrorNotExist
 | 
							return nil, ErrPushMirrorNotExist
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return m, nil
 | 
						return mirror, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetPushMirrorsByRepoID returns push-mirror information of a repository.
 | 
					// GetPushMirrorsByRepoID returns push-mirror information of a repository.
 | 
				
			||||||
func GetPushMirrorsByRepoID(repoID int64) ([]*PushMirror, error) {
 | 
					func GetPushMirrorsByRepoID(ctx context.Context, repoID int64, listOptions db.ListOptions) ([]*PushMirror, int64, error) {
 | 
				
			||||||
 | 
						sess := db.GetEngine(ctx).Where("repo_id = ?", repoID)
 | 
				
			||||||
 | 
						if listOptions.Page != 0 {
 | 
				
			||||||
 | 
							sess = db.SetSessionPagination(sess, &listOptions)
 | 
				
			||||||
 | 
							mirrors := make([]*PushMirror, 0, listOptions.PageSize)
 | 
				
			||||||
 | 
							count, err := sess.FindAndCount(&mirrors)
 | 
				
			||||||
 | 
							return mirrors, count, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	mirrors := make([]*PushMirror, 0, 10)
 | 
						mirrors := make([]*PushMirror, 0, 10)
 | 
				
			||||||
	return mirrors, db.GetEngine(db.DefaultContext).Where("repo_id=?", repoID).Find(&mirrors)
 | 
						count, err := sess.FindAndCount(&mirrors)
 | 
				
			||||||
 | 
						return mirrors, count, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetPushMirrorsSyncedOnCommit returns push-mirrors for this repo that should be updated by new commits
 | 
					// GetPushMirrorsSyncedOnCommit returns push-mirrors for this repo that should be updated by new commits
 | 
				
			||||||
@@ -103,8 +128,8 @@ func GetPushMirrorsSyncedOnCommit(repoID int64) ([]*PushMirror, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// PushMirrorsIterate iterates all push-mirror repositories.
 | 
					// PushMirrorsIterate iterates all push-mirror repositories.
 | 
				
			||||||
func PushMirrorsIterate(limit int, f func(idx int, bean interface{}) error) error {
 | 
					func PushMirrorsIterate(ctx context.Context, limit int, f func(idx int, bean interface{}) error) error {
 | 
				
			||||||
	return db.GetEngine(db.DefaultContext).
 | 
						return db.GetEngine(ctx).
 | 
				
			||||||
		Where("last_update + (`interval` / ?) <= ?", time.Second, time.Now().Unix()).
 | 
							Where("last_update + (`interval` / ?) <= ?", time.Second, time.Now().Unix()).
 | 
				
			||||||
		And("`interval` != 0").
 | 
							And("`interval` != 0").
 | 
				
			||||||
		OrderBy("last_update ASC").
 | 
							OrderBy("last_update ASC").
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,7 @@ import (
 | 
				
			|||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"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"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/timeutil"
 | 
						"code.gitea.io/gitea/modules/timeutil"
 | 
				
			||||||
@@ -20,20 +21,20 @@ func TestPushMirrorsIterate(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	now := timeutil.TimeStampNow()
 | 
						now := timeutil.TimeStampNow()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	repo_model.InsertPushMirror(&repo_model.PushMirror{
 | 
						repo_model.InsertPushMirror(db.DefaultContext, &repo_model.PushMirror{
 | 
				
			||||||
		RemoteName:     "test-1",
 | 
							RemoteName:     "test-1",
 | 
				
			||||||
		LastUpdateUnix: now,
 | 
							LastUpdateUnix: now,
 | 
				
			||||||
		Interval:       1,
 | 
							Interval:       1,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	long, _ := time.ParseDuration("24h")
 | 
						long, _ := time.ParseDuration("24h")
 | 
				
			||||||
	repo_model.InsertPushMirror(&repo_model.PushMirror{
 | 
						repo_model.InsertPushMirror(db.DefaultContext, &repo_model.PushMirror{
 | 
				
			||||||
		RemoteName:     "test-2",
 | 
							RemoteName:     "test-2",
 | 
				
			||||||
		LastUpdateUnix: now,
 | 
							LastUpdateUnix: now,
 | 
				
			||||||
		Interval:       long,
 | 
							Interval:       long,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	repo_model.InsertPushMirror(&repo_model.PushMirror{
 | 
						repo_model.InsertPushMirror(db.DefaultContext, &repo_model.PushMirror{
 | 
				
			||||||
		RemoteName:     "test-3",
 | 
							RemoteName:     "test-3",
 | 
				
			||||||
		LastUpdateUnix: now,
 | 
							LastUpdateUnix: now,
 | 
				
			||||||
		Interval:       0,
 | 
							Interval:       0,
 | 
				
			||||||
@@ -41,7 +42,7 @@ func TestPushMirrorsIterate(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	time.Sleep(1 * time.Millisecond)
 | 
						time.Sleep(1 * time.Millisecond)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	repo_model.PushMirrorsIterate(1, func(idx int, bean interface{}) error {
 | 
						repo_model.PushMirrorsIterate(db.DefaultContext, 1, func(idx int, bean interface{}) error {
 | 
				
			||||||
		m, ok := bean.(*repo_model.PushMirror)
 | 
							m, ok := bean.(*repo_model.PushMirror)
 | 
				
			||||||
		assert.True(t, ok)
 | 
							assert.True(t, ok)
 | 
				
			||||||
		assert.Equal(t, "test-1", m.RemoteName)
 | 
							assert.Equal(t, "test-1", m.RemoteName)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -393,7 +393,7 @@ func repoAssignment(ctx *Context, repo *repo_model.Repository) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pushMirrors, err := repo_model.GetPushMirrorsByRepoID(repo.ID)
 | 
						pushMirrors, _, err := repo_model.GetPushMirrorsByRepoID(ctx, repo.ID, db.ListOptions{})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.ServerError("GetPushMirrorsByRepoID", err)
 | 
							ctx.ServerError("GetPushMirrorsByRepoID", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										39
									
								
								modules/convert/mirror.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								modules/convert/mirror.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					// Copyright 2022 The Gitea Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a MIT-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package convert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						repo_model "code.gitea.io/gitea/models/repo"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/git"
 | 
				
			||||||
 | 
						api "code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ToPushMirror convert from repo_model.PushMirror and remoteAddress to api.TopicResponse
 | 
				
			||||||
 | 
					func ToPushMirror(pm *repo_model.PushMirror) (*api.PushMirror, error) {
 | 
				
			||||||
 | 
						repo := pm.GetRepository()
 | 
				
			||||||
 | 
						remoteAddress, err := getRemoteAddress(repo, pm.RemoteName)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &api.PushMirror{
 | 
				
			||||||
 | 
							RepoName:       repo.Name,
 | 
				
			||||||
 | 
							RemoteName:     pm.RemoteName,
 | 
				
			||||||
 | 
							RemoteAddress:  remoteAddress,
 | 
				
			||||||
 | 
							CreatedUnix:    pm.CreatedUnix.FormatLong(),
 | 
				
			||||||
 | 
							LastUpdateUnix: pm.LastUpdateUnix.FormatLong(),
 | 
				
			||||||
 | 
							LastError:      pm.LastError,
 | 
				
			||||||
 | 
							Interval:       pm.Interval.String(),
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getRemoteAddress(repo *repo_model.Repository, remoteName string) (string, error) {
 | 
				
			||||||
 | 
						url, err := git.GetRemoteURL(git.DefaultContext, repo.RepoPath(), remoteName)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return "", err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// remove confidential information
 | 
				
			||||||
 | 
						url.User = nil
 | 
				
			||||||
 | 
						return url.String(), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										25
									
								
								modules/structs/mirror.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								modules/structs/mirror.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					// Copyright 2021 The Gitea Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a MIT-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package structs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CreatePushMirrorOption represents need information to create a push mirror of a repository.
 | 
				
			||||||
 | 
					type CreatePushMirrorOption struct {
 | 
				
			||||||
 | 
						RemoteAddress  string `json:"remote_address"`
 | 
				
			||||||
 | 
						RemoteUsername string `json:"remote_username"`
 | 
				
			||||||
 | 
						RemotePassword string `json:"remote_password"`
 | 
				
			||||||
 | 
						Interval       string `json:"interval"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PushMirror represents information of a push mirror
 | 
				
			||||||
 | 
					// swagger:model
 | 
				
			||||||
 | 
					type PushMirror struct {
 | 
				
			||||||
 | 
						RepoName       string `json:"repo_name"`
 | 
				
			||||||
 | 
						RemoteName     string `json:"remote_name"`
 | 
				
			||||||
 | 
						RemoteAddress  string `json:"remote_address"`
 | 
				
			||||||
 | 
						CreatedUnix    string `json:"created"`
 | 
				
			||||||
 | 
						LastUpdateUnix string `json:"last_update"`
 | 
				
			||||||
 | 
						LastError      string `json:"last_error"`
 | 
				
			||||||
 | 
						Interval       string `json:"interval"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -982,6 +982,15 @@ func Routes() *web.Route {
 | 
				
			|||||||
					})
 | 
										})
 | 
				
			||||||
				}, reqRepoReader(unit.TypeReleases))
 | 
									}, reqRepoReader(unit.TypeReleases))
 | 
				
			||||||
				m.Post("/mirror-sync", reqToken(), reqRepoWriter(unit.TypeCode), repo.MirrorSync)
 | 
									m.Post("/mirror-sync", reqToken(), reqRepoWriter(unit.TypeCode), repo.MirrorSync)
 | 
				
			||||||
 | 
									m.Post("/push_mirrors-sync", reqAdmin(), repo.PushMirrorSync)
 | 
				
			||||||
 | 
									m.Group("/push_mirrors", func() {
 | 
				
			||||||
 | 
										m.Combo("").Get(repo.ListPushMirrors).
 | 
				
			||||||
 | 
											Post(bind(api.CreatePushMirrorOption{}), repo.AddPushMirror)
 | 
				
			||||||
 | 
										m.Combo("/{name}").
 | 
				
			||||||
 | 
											Delete(repo.DeletePushMirrorByRemoteName).
 | 
				
			||||||
 | 
											Get(repo.GetPushMirrorByName)
 | 
				
			||||||
 | 
									}, reqAdmin())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				m.Get("/editorconfig/{filename}", context.ReferencesGitRepo(), context.RepoRefForAPI, reqRepoReader(unit.TypeCode), repo.GetEditorconfig)
 | 
									m.Get("/editorconfig/{filename}", context.ReferencesGitRepo(), context.RepoRefForAPI, reqRepoReader(unit.TypeCode), repo.GetEditorconfig)
 | 
				
			||||||
				m.Group("/pulls", func() {
 | 
									m.Group("/pulls", func() {
 | 
				
			||||||
					m.Combo("").Get(repo.ListPullRequests).
 | 
										m.Combo("").Get(repo.ListPullRequests).
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,13 +6,25 @@ package repo
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
 | 
						"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/unit"
 | 
						"code.gitea.io/gitea/models/unit"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/context"
 | 
						"code.gitea.io/gitea/modules/context"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/convert"
 | 
				
			||||||
	mirror_module "code.gitea.io/gitea/modules/mirror"
 | 
						mirror_module "code.gitea.io/gitea/modules/mirror"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/setting"
 | 
						"code.gitea.io/gitea/modules/setting"
 | 
				
			||||||
 | 
						api "code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/util"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/web"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/routers/api/v1/utils"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/services/forms"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/services/migrations"
 | 
				
			||||||
 | 
						mirror_service "code.gitea.io/gitea/services/mirror"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// MirrorSync adds a mirrored repository to the sync queue
 | 
					// MirrorSync adds a mirrored repository to the sync queue
 | 
				
			||||||
@@ -63,3 +75,317 @@ func MirrorSync(ctx *context.APIContext) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	ctx.Status(http.StatusOK)
 | 
						ctx.Status(http.StatusOK)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PushMirrorSync adds all push mirrored repositories to the sync queue
 | 
				
			||||||
 | 
					func PushMirrorSync(ctx *context.APIContext) {
 | 
				
			||||||
 | 
						// swagger:operation POST /repos/{owner}/{repo}/push_mirrors-sync repository repoPushMirrorSync
 | 
				
			||||||
 | 
						// ---
 | 
				
			||||||
 | 
						// summary: Sync all push mirrored repository
 | 
				
			||||||
 | 
						// produces:
 | 
				
			||||||
 | 
						// - application/json
 | 
				
			||||||
 | 
						// parameters:
 | 
				
			||||||
 | 
						// - name: owner
 | 
				
			||||||
 | 
						//   in: path
 | 
				
			||||||
 | 
						//   description: owner of the repo to sync
 | 
				
			||||||
 | 
						//   type: string
 | 
				
			||||||
 | 
						//   required: true
 | 
				
			||||||
 | 
						// - name: repo
 | 
				
			||||||
 | 
						//   in: path
 | 
				
			||||||
 | 
						//   description: name of the repo to sync
 | 
				
			||||||
 | 
						//   type: string
 | 
				
			||||||
 | 
						//   required: true
 | 
				
			||||||
 | 
						// responses:
 | 
				
			||||||
 | 
						//   "200":
 | 
				
			||||||
 | 
						//     "$ref": "#/responses/empty"
 | 
				
			||||||
 | 
						//   "400":
 | 
				
			||||||
 | 
						//     "$ref": "#/responses/error"
 | 
				
			||||||
 | 
						//   "403":
 | 
				
			||||||
 | 
						//     "$ref": "#/responses/forbidden"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !setting.Mirror.Enabled {
 | 
				
			||||||
 | 
							ctx.Error(http.StatusBadRequest, "PushMirrorSync", "Mirror feature is disabled")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// Get All push mirrors of a specific repo
 | 
				
			||||||
 | 
						pushMirrors, _, err := repo_model.GetPushMirrorsByRepoID(ctx, ctx.Repo.Repository.ID, db.ListOptions{})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.Error(http.StatusNotFound, "PushMirrorSync", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, mirror := range pushMirrors {
 | 
				
			||||||
 | 
							ok := mirror_service.SyncPushMirror(ctx, mirror.ID)
 | 
				
			||||||
 | 
							if !ok {
 | 
				
			||||||
 | 
								ctx.Error(http.StatusInternalServerError, "PushMirrorSync", "error occurred when syncing push mirror "+mirror.RemoteName)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.Status(http.StatusOK)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ListPushMirrors get list of push mirrors of a repository
 | 
				
			||||||
 | 
					func ListPushMirrors(ctx *context.APIContext) {
 | 
				
			||||||
 | 
						// swagger:operation GET /repos/{owner}/{repo}/push_mirrors repository repoListPushMirrors
 | 
				
			||||||
 | 
						// ---
 | 
				
			||||||
 | 
						// summary: Get all push mirrors of the repository
 | 
				
			||||||
 | 
						// produces:
 | 
				
			||||||
 | 
						// - application/json
 | 
				
			||||||
 | 
						// parameters:
 | 
				
			||||||
 | 
						// - name: owner
 | 
				
			||||||
 | 
						//   in: path
 | 
				
			||||||
 | 
						//   description: owner of the repo
 | 
				
			||||||
 | 
						//   type: string
 | 
				
			||||||
 | 
						//   required: true
 | 
				
			||||||
 | 
						// - name: repo
 | 
				
			||||||
 | 
						//   in: path
 | 
				
			||||||
 | 
						//   description: name of the repo
 | 
				
			||||||
 | 
						//   type: string
 | 
				
			||||||
 | 
						//   required: true
 | 
				
			||||||
 | 
						// - name: page
 | 
				
			||||||
 | 
						//   in: query
 | 
				
			||||||
 | 
						//   description: page number of results to return (1-based)
 | 
				
			||||||
 | 
						//   type: integer
 | 
				
			||||||
 | 
						// - name: limit
 | 
				
			||||||
 | 
						//   in: query
 | 
				
			||||||
 | 
						//   description: page size of results
 | 
				
			||||||
 | 
						//   type: integer
 | 
				
			||||||
 | 
						// responses:
 | 
				
			||||||
 | 
						//   "200":
 | 
				
			||||||
 | 
						//     "$ref": "#/responses/PushMirrorList"
 | 
				
			||||||
 | 
						//   "400":
 | 
				
			||||||
 | 
						//     "$ref": "#/responses/error"
 | 
				
			||||||
 | 
						//   "403":
 | 
				
			||||||
 | 
						//     "$ref": "#/responses/forbidden"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !setting.Mirror.Enabled {
 | 
				
			||||||
 | 
							ctx.Error(http.StatusBadRequest, "GetPushMirrorsByRepoID", "Mirror feature is disabled")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						repo := ctx.Repo.Repository
 | 
				
			||||||
 | 
						// Get all push mirrors for the specified repository.
 | 
				
			||||||
 | 
						pushMirrors, count, err := repo_model.GetPushMirrorsByRepoID(ctx, repo.ID, utils.GetListOptions(ctx))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.Error(http.StatusNotFound, "GetPushMirrorsByRepoID", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						responsePushMirrors := make([]*api.PushMirror, 0, len(pushMirrors))
 | 
				
			||||||
 | 
						for _, mirror := range pushMirrors {
 | 
				
			||||||
 | 
							m, err := convert.ToPushMirror(mirror)
 | 
				
			||||||
 | 
							if err == nil {
 | 
				
			||||||
 | 
								responsePushMirrors = append(responsePushMirrors, m)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ctx.SetLinkHeader(len(responsePushMirrors), utils.GetListOptions(ctx).PageSize)
 | 
				
			||||||
 | 
						ctx.SetTotalCountHeader(count)
 | 
				
			||||||
 | 
						ctx.JSON(http.StatusOK, responsePushMirrors)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetPushMirrorByName get push mirror of a repository by name
 | 
				
			||||||
 | 
					func GetPushMirrorByName(ctx *context.APIContext) {
 | 
				
			||||||
 | 
						// swagger:operation GET /repos/{owner}/{repo}/push_mirrors/{name} repository repoGetPushMirrorByRemoteName
 | 
				
			||||||
 | 
						// ---
 | 
				
			||||||
 | 
						// summary: Get push mirror of the repository by remoteName
 | 
				
			||||||
 | 
						// produces:
 | 
				
			||||||
 | 
						// - application/json
 | 
				
			||||||
 | 
						// parameters:
 | 
				
			||||||
 | 
						// - name: owner
 | 
				
			||||||
 | 
						//   in: path
 | 
				
			||||||
 | 
						//   description: owner of the repo
 | 
				
			||||||
 | 
						//   type: string
 | 
				
			||||||
 | 
						//   required: true
 | 
				
			||||||
 | 
						// - name: repo
 | 
				
			||||||
 | 
						//   in: path
 | 
				
			||||||
 | 
						//   description: name of the repo
 | 
				
			||||||
 | 
						//   type: string
 | 
				
			||||||
 | 
						//   required: true
 | 
				
			||||||
 | 
						// - name: name
 | 
				
			||||||
 | 
						//   in: path
 | 
				
			||||||
 | 
						//   description: remote name of push mirror
 | 
				
			||||||
 | 
						//   type: string
 | 
				
			||||||
 | 
						//   required: true
 | 
				
			||||||
 | 
						// responses:
 | 
				
			||||||
 | 
						//   "200":
 | 
				
			||||||
 | 
						//     "$ref": "#/responses/PushMirror"
 | 
				
			||||||
 | 
						//   "400":
 | 
				
			||||||
 | 
						//     "$ref": "#/responses/error"
 | 
				
			||||||
 | 
						//   "403":
 | 
				
			||||||
 | 
						//     "$ref": "#/responses/forbidden"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !setting.Mirror.Enabled {
 | 
				
			||||||
 | 
							ctx.Error(http.StatusBadRequest, "GetPushMirrorByRemoteName", "Mirror feature is disabled")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mirrorName := ctx.Params(":name")
 | 
				
			||||||
 | 
						// Get push mirror of a specific repo by remoteName
 | 
				
			||||||
 | 
						pushMirror, err := repo_model.GetPushMirror(ctx, repo_model.PushMirrorOptions{RepoID: ctx.Repo.Repository.ID, RemoteName: mirrorName})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.Error(http.StatusNotFound, "GetPushMirrors", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						m, err := convert.ToPushMirror(pushMirror)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.ServerError("GetPushMirrorByRemoteName", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ctx.JSON(http.StatusOK, m)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AddPushMirror adds a push mirror to a repository
 | 
				
			||||||
 | 
					func AddPushMirror(ctx *context.APIContext) {
 | 
				
			||||||
 | 
						// swagger:operation POST /repos/{owner}/{repo}/push_mirrors repository repoAddPushMirror
 | 
				
			||||||
 | 
						// ---
 | 
				
			||||||
 | 
						// summary: add a push mirror to the repository
 | 
				
			||||||
 | 
						// consumes:
 | 
				
			||||||
 | 
						// - application/json
 | 
				
			||||||
 | 
						// produces:
 | 
				
			||||||
 | 
						// - application/json
 | 
				
			||||||
 | 
						// parameters:
 | 
				
			||||||
 | 
						// - name: owner
 | 
				
			||||||
 | 
						//   in: path
 | 
				
			||||||
 | 
						//   description: owner of the repo
 | 
				
			||||||
 | 
						//   type: string
 | 
				
			||||||
 | 
						//   required: true
 | 
				
			||||||
 | 
						// - name: repo
 | 
				
			||||||
 | 
						//   in: path
 | 
				
			||||||
 | 
						//   description: name of the repo
 | 
				
			||||||
 | 
						//   type: string
 | 
				
			||||||
 | 
						//   required: true
 | 
				
			||||||
 | 
						// - name: body
 | 
				
			||||||
 | 
						//   in: body
 | 
				
			||||||
 | 
						//   schema:
 | 
				
			||||||
 | 
						//     "$ref": "#/definitions/CreatePushMirrorOption"
 | 
				
			||||||
 | 
						// responses:
 | 
				
			||||||
 | 
						//   "201":
 | 
				
			||||||
 | 
						//     "$ref": "#/responses/PushMirror"
 | 
				
			||||||
 | 
						//   "403":
 | 
				
			||||||
 | 
						//     "$ref": "#/responses/forbidden"
 | 
				
			||||||
 | 
						//   "400":
 | 
				
			||||||
 | 
						//     "$ref": "#/responses/error"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !setting.Mirror.Enabled {
 | 
				
			||||||
 | 
							ctx.Error(http.StatusBadRequest, "AddPushMirror", "Mirror feature is disabled")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pushMirror := web.GetForm(ctx).(*api.CreatePushMirrorOption)
 | 
				
			||||||
 | 
						CreatePushMirror(ctx, pushMirror)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeletePushMirrorByRemoteName deletes a push mirror from a repository by remoteName
 | 
				
			||||||
 | 
					func DeletePushMirrorByRemoteName(ctx *context.APIContext) {
 | 
				
			||||||
 | 
						// swagger:operation DELETE /repos/{owner}/{repo}/push_mirrors/{name} repository repoDeletePushMirror
 | 
				
			||||||
 | 
						// ---
 | 
				
			||||||
 | 
						// summary: deletes a push mirror from a repository by remoteName
 | 
				
			||||||
 | 
						// produces:
 | 
				
			||||||
 | 
						// - application/json
 | 
				
			||||||
 | 
						// parameters:
 | 
				
			||||||
 | 
						// - name: owner
 | 
				
			||||||
 | 
						//   in: path
 | 
				
			||||||
 | 
						//   description: owner of the repo
 | 
				
			||||||
 | 
						//   type: string
 | 
				
			||||||
 | 
						//   required: true
 | 
				
			||||||
 | 
						// - name: repo
 | 
				
			||||||
 | 
						//   in: path
 | 
				
			||||||
 | 
						//   description: name of the repo
 | 
				
			||||||
 | 
						//   type: string
 | 
				
			||||||
 | 
						//   required: true
 | 
				
			||||||
 | 
						// - name: name
 | 
				
			||||||
 | 
						//   in: path
 | 
				
			||||||
 | 
						//   description: remote name of the pushMirror
 | 
				
			||||||
 | 
						//   type: string
 | 
				
			||||||
 | 
						//   required: true
 | 
				
			||||||
 | 
						// responses:
 | 
				
			||||||
 | 
						//   "204":
 | 
				
			||||||
 | 
						//     "$ref": "#/responses/empty"
 | 
				
			||||||
 | 
						//   "404":
 | 
				
			||||||
 | 
						//     "$ref": "#/responses/notFound"
 | 
				
			||||||
 | 
						//   "400":
 | 
				
			||||||
 | 
						//     "$ref": "#/responses/error"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !setting.Mirror.Enabled {
 | 
				
			||||||
 | 
							ctx.Error(http.StatusBadRequest, "DeletePushMirrorByName", "Mirror feature is disabled")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						remoteName := ctx.Params(":name")
 | 
				
			||||||
 | 
						// Delete push mirror on repo by name.
 | 
				
			||||||
 | 
						err := repo_model.DeletePushMirrors(ctx, repo_model.PushMirrorOptions{RepoID: ctx.Repo.Repository.ID, RemoteName: remoteName})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.Error(http.StatusNotFound, "DeletePushMirrors", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ctx.Status(http.StatusNoContent)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func CreatePushMirror(ctx *context.APIContext, mirrorOption *api.CreatePushMirrorOption) {
 | 
				
			||||||
 | 
						repo := ctx.Repo.Repository
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						interval, err := time.ParseDuration(mirrorOption.Interval)
 | 
				
			||||||
 | 
						if err != nil || (interval != 0 && interval < setting.Mirror.MinInterval) {
 | 
				
			||||||
 | 
							ctx.Error(http.StatusBadRequest, "CreatePushMirror", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						address, err := forms.ParseRemoteAddr(mirrorOption.RemoteAddress, mirrorOption.RemoteUsername, mirrorOption.RemotePassword)
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							err = migrations.IsMigrateURLAllowed(address, ctx.ContextUser)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							HandleRemoteAddressError(ctx, err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						remoteSuffix, err := util.CryptoRandomString(10)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.ServerError("CryptoRandomString", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pushMirror := &repo_model.PushMirror{
 | 
				
			||||||
 | 
							RepoID:     repo.ID,
 | 
				
			||||||
 | 
							Repo:       repo,
 | 
				
			||||||
 | 
							RemoteName: fmt.Sprintf("remote_mirror_%s", remoteSuffix),
 | 
				
			||||||
 | 
							Interval:   interval,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err = repo_model.InsertPushMirror(ctx, pushMirror); err != nil {
 | 
				
			||||||
 | 
							ctx.ServerError("InsertPushMirror", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// if the registration of the push mirrorOption fails remove it from the database
 | 
				
			||||||
 | 
						if err = mirror_service.AddPushMirrorRemote(ctx, pushMirror, address); err != nil {
 | 
				
			||||||
 | 
							if err := repo_model.DeletePushMirrors(ctx, repo_model.PushMirrorOptions{ID: pushMirror.ID, RepoID: pushMirror.RepoID}); err != nil {
 | 
				
			||||||
 | 
								ctx.ServerError("DeletePushMirrors", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx.ServerError("AddPushMirrorRemote", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						m, err := convert.ToPushMirror(pushMirror)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.ServerError("ToPushMirror", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ctx.JSON(http.StatusOK, m)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func HandleRemoteAddressError(ctx *context.APIContext, err error) {
 | 
				
			||||||
 | 
						if models.IsErrInvalidCloneAddr(err) {
 | 
				
			||||||
 | 
							addrErr := err.(*models.ErrInvalidCloneAddr)
 | 
				
			||||||
 | 
							switch {
 | 
				
			||||||
 | 
							case addrErr.IsProtocolInvalid:
 | 
				
			||||||
 | 
								ctx.Error(http.StatusBadRequest, "CreatePushMirror", "Invalid mirror protocol")
 | 
				
			||||||
 | 
							case addrErr.IsURLError:
 | 
				
			||||||
 | 
								ctx.Error(http.StatusBadRequest, "CreatePushMirror", "Invalid Url ")
 | 
				
			||||||
 | 
							case addrErr.IsPermissionDenied:
 | 
				
			||||||
 | 
								ctx.Error(http.StatusUnauthorized, "CreatePushMirror", "Permission denied")
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								ctx.Error(http.StatusBadRequest, "CreatePushMirror", "Unknown error")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -169,4 +169,7 @@ type swaggerParameterBodies struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// in:body
 | 
						// in:body
 | 
				
			||||||
	CreateWikiPageOptions api.CreateWikiPageOptions
 | 
						CreateWikiPageOptions api.CreateWikiPageOptions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// in:body
 | 
				
			||||||
 | 
						CreatePushMirrorOption api.CreatePushMirrorOption
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -345,6 +345,20 @@ type swaggerWikiCommitList struct {
 | 
				
			|||||||
	Body api.WikiCommitList `json:"body"`
 | 
						Body api.WikiCommitList `json:"body"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PushMirror
 | 
				
			||||||
 | 
					// swagger:response PushMirror
 | 
				
			||||||
 | 
					type swaggerPushMirror struct {
 | 
				
			||||||
 | 
						// in:body
 | 
				
			||||||
 | 
						Body api.PushMirror `json:"body"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PushMirrorList
 | 
				
			||||||
 | 
					// swagger:response PushMirrorList
 | 
				
			||||||
 | 
					type swaggerPushMirrorList struct {
 | 
				
			||||||
 | 
						// in:body
 | 
				
			||||||
 | 
						Body []api.PushMirror `json:"body"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RepoCollaboratorPermission
 | 
					// RepoCollaboratorPermission
 | 
				
			||||||
// swagger:response RepoCollaboratorPermission
 | 
					// swagger:response RepoCollaboratorPermission
 | 
				
			||||||
type swaggerRepoCollaboratorPermission struct {
 | 
					type swaggerRepoCollaboratorPermission struct {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -90,7 +90,7 @@ func SettingsCtxData(ctx *context.Context) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		ctx.Data["StatsIndexerStatus"] = status
 | 
							ctx.Data["StatsIndexerStatus"] = status
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	pushMirrors, err := repo_model.GetPushMirrorsByRepoID(ctx.Repo.Repository.ID)
 | 
						pushMirrors, _, err := repo_model.GetPushMirrorsByRepoID(ctx, ctx.Repo.Repository.ID, db.ListOptions{})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.ServerError("GetPushMirrorsByRepoID", err)
 | 
							ctx.ServerError("GetPushMirrorsByRepoID", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@@ -284,7 +284,7 @@ func SettingsPost(ctx *context.Context) {
 | 
				
			|||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		m, err := selectPushMirrorByForm(form, repo)
 | 
							m, err := selectPushMirrorByForm(ctx, form, repo)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			ctx.NotFound("", nil)
 | 
								ctx.NotFound("", nil)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
@@ -305,7 +305,7 @@ func SettingsPost(ctx *context.Context) {
 | 
				
			|||||||
		// as an error on the UI for this action
 | 
							// as an error on the UI for this action
 | 
				
			||||||
		ctx.Data["Err_RepoName"] = nil
 | 
							ctx.Data["Err_RepoName"] = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		m, err := selectPushMirrorByForm(form, repo)
 | 
							m, err := selectPushMirrorByForm(ctx, form, repo)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			ctx.NotFound("", nil)
 | 
								ctx.NotFound("", nil)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
@@ -316,7 +316,7 @@ func SettingsPost(ctx *context.Context) {
 | 
				
			|||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err = repo_model.DeletePushMirrorByID(m.ID); err != nil {
 | 
							if err = repo_model.DeletePushMirrors(ctx, repo_model.PushMirrorOptions{ID: m.ID, RepoID: m.RepoID}); err != nil {
 | 
				
			||||||
			ctx.ServerError("DeletePushMirrorByID", err)
 | 
								ctx.ServerError("DeletePushMirrorByID", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -364,14 +364,14 @@ func SettingsPost(ctx *context.Context) {
 | 
				
			|||||||
			SyncOnCommit: form.PushMirrorSyncOnCommit,
 | 
								SyncOnCommit: form.PushMirrorSyncOnCommit,
 | 
				
			||||||
			Interval:     interval,
 | 
								Interval:     interval,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if err := repo_model.InsertPushMirror(m); err != nil {
 | 
							if err := repo_model.InsertPushMirror(ctx, m); err != nil {
 | 
				
			||||||
			ctx.ServerError("InsertPushMirror", err)
 | 
								ctx.ServerError("InsertPushMirror", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := mirror_service.AddPushMirrorRemote(ctx, m, address); err != nil {
 | 
							if err := mirror_service.AddPushMirrorRemote(ctx, m, address); err != nil {
 | 
				
			||||||
			if err := repo_model.DeletePushMirrorByID(m.ID); err != nil {
 | 
								if err := repo_model.DeletePushMirrors(ctx, repo_model.PushMirrorOptions{ID: m.ID, RepoID: m.RepoID}); err != nil {
 | 
				
			||||||
				log.Error("DeletePushMirrorByID %v", err)
 | 
									log.Error("DeletePushMirrors %v", err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			ctx.ServerError("AddPushMirrorRemote", err)
 | 
								ctx.ServerError("AddPushMirrorRemote", err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
@@ -1222,13 +1222,13 @@ func SettingsDeleteAvatar(ctx *context.Context) {
 | 
				
			|||||||
	ctx.Redirect(ctx.Repo.RepoLink + "/settings")
 | 
						ctx.Redirect(ctx.Repo.RepoLink + "/settings")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func selectPushMirrorByForm(form *forms.RepoSettingForm, repo *repo_model.Repository) (*repo_model.PushMirror, error) {
 | 
					func selectPushMirrorByForm(ctx *context.Context, form *forms.RepoSettingForm, repo *repo_model.Repository) (*repo_model.PushMirror, error) {
 | 
				
			||||||
	id, err := strconv.ParseInt(form.PushMirrorID, 10, 64)
 | 
						id, err := strconv.ParseInt(form.PushMirrorID, 10, 64)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pushMirrors, err := repo_model.GetPushMirrorsByRepoID(repo.ID)
 | 
						pushMirrors, _, err := repo_model.GetPushMirrorsByRepoID(ctx, repo.ID, db.ListOptions{})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -106,7 +106,7 @@ func Update(ctx context.Context, pullLimit, pushLimit int) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	pushMirrorsRequested := 0
 | 
						pushMirrorsRequested := 0
 | 
				
			||||||
	if pushLimit != 0 {
 | 
						if pushLimit != 0 {
 | 
				
			||||||
		if err := repo_model.PushMirrorsIterate(pushLimit, func(idx int, bean interface{}) error {
 | 
							if err := repo_model.PushMirrorsIterate(ctx, pushLimit, func(idx int, bean interface{}) error {
 | 
				
			||||||
			if err := handler(idx, bean); err != nil {
 | 
								if err := handler(idx, bean); err != nil {
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -94,7 +94,7 @@ func SyncPushMirror(ctx context.Context, mirrorID int64) bool {
 | 
				
			|||||||
		log.Error("PANIC whilst syncPushMirror[%d] Panic: %v\nStacktrace: %s", mirrorID, err, log.Stack(2))
 | 
							log.Error("PANIC whilst syncPushMirror[%d] Panic: %v\nStacktrace: %s", mirrorID, err, log.Stack(2))
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m, err := repo_model.GetPushMirrorByID(mirrorID)
 | 
						m, err := repo_model.GetPushMirror(ctx, repo_model.PushMirrorOptions{ID: mirrorID})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Error("GetPushMirrorByID [%d]: %v", mirrorID, err)
 | 
							log.Error("GetPushMirrorByID [%d]: %v", mirrorID, err)
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
@@ -116,7 +116,7 @@ func SyncPushMirror(ctx context.Context, mirrorID int64) bool {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	m.LastUpdateUnix = timeutil.TimeStampNow()
 | 
						m.LastUpdateUnix = timeutil.TimeStampNow()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := repo_model.UpdatePushMirror(m); err != nil {
 | 
						if err := repo_model.UpdatePushMirror(ctx, m); err != nil {
 | 
				
			||||||
		log.Error("UpdatePushMirror [%d]: %v", m.ID, err)
 | 
							log.Error("UpdatePushMirror [%d]: %v", m.ID, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8774,6 +8774,233 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "/repos/{owner}/{repo}/push_mirrors": {
 | 
				
			||||||
 | 
					      "get": {
 | 
				
			||||||
 | 
					        "produces": [
 | 
				
			||||||
 | 
					          "application/json"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "tags": [
 | 
				
			||||||
 | 
					          "repository"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "summary": "Get all push mirrors of the repository",
 | 
				
			||||||
 | 
					        "operationId": "repoListPushMirrors",
 | 
				
			||||||
 | 
					        "parameters": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "type": "string",
 | 
				
			||||||
 | 
					            "description": "owner of the repo",
 | 
				
			||||||
 | 
					            "name": "owner",
 | 
				
			||||||
 | 
					            "in": "path",
 | 
				
			||||||
 | 
					            "required": true
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "type": "string",
 | 
				
			||||||
 | 
					            "description": "name of the repo",
 | 
				
			||||||
 | 
					            "name": "repo",
 | 
				
			||||||
 | 
					            "in": "path",
 | 
				
			||||||
 | 
					            "required": true
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "type": "integer",
 | 
				
			||||||
 | 
					            "description": "page number of results to return (1-based)",
 | 
				
			||||||
 | 
					            "name": "page",
 | 
				
			||||||
 | 
					            "in": "query"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "type": "integer",
 | 
				
			||||||
 | 
					            "description": "page size of results",
 | 
				
			||||||
 | 
					            "name": "limit",
 | 
				
			||||||
 | 
					            "in": "query"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "responses": {
 | 
				
			||||||
 | 
					          "200": {
 | 
				
			||||||
 | 
					            "$ref": "#/responses/PushMirrorList"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "400": {
 | 
				
			||||||
 | 
					            "$ref": "#/responses/error"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "403": {
 | 
				
			||||||
 | 
					            "$ref": "#/responses/forbidden"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "post": {
 | 
				
			||||||
 | 
					        "consumes": [
 | 
				
			||||||
 | 
					          "application/json"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "produces": [
 | 
				
			||||||
 | 
					          "application/json"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "tags": [
 | 
				
			||||||
 | 
					          "repository"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "summary": "add a push mirror to the repository",
 | 
				
			||||||
 | 
					        "operationId": "repoAddPushMirror",
 | 
				
			||||||
 | 
					        "parameters": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "type": "string",
 | 
				
			||||||
 | 
					            "description": "owner of the repo",
 | 
				
			||||||
 | 
					            "name": "owner",
 | 
				
			||||||
 | 
					            "in": "path",
 | 
				
			||||||
 | 
					            "required": true
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "type": "string",
 | 
				
			||||||
 | 
					            "description": "name of the repo",
 | 
				
			||||||
 | 
					            "name": "repo",
 | 
				
			||||||
 | 
					            "in": "path",
 | 
				
			||||||
 | 
					            "required": true
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "name": "body",
 | 
				
			||||||
 | 
					            "in": "body",
 | 
				
			||||||
 | 
					            "schema": {
 | 
				
			||||||
 | 
					              "$ref": "#/definitions/CreatePushMirrorOption"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "responses": {
 | 
				
			||||||
 | 
					          "201": {
 | 
				
			||||||
 | 
					            "$ref": "#/responses/PushMirror"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "400": {
 | 
				
			||||||
 | 
					            "$ref": "#/responses/error"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "403": {
 | 
				
			||||||
 | 
					            "$ref": "#/responses/forbidden"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "/repos/{owner}/{repo}/push_mirrors-sync": {
 | 
				
			||||||
 | 
					      "post": {
 | 
				
			||||||
 | 
					        "produces": [
 | 
				
			||||||
 | 
					          "application/json"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "tags": [
 | 
				
			||||||
 | 
					          "repository"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "summary": "Sync all push mirrored repository",
 | 
				
			||||||
 | 
					        "operationId": "repoPushMirrorSync",
 | 
				
			||||||
 | 
					        "parameters": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "type": "string",
 | 
				
			||||||
 | 
					            "description": "owner of the repo to sync",
 | 
				
			||||||
 | 
					            "name": "owner",
 | 
				
			||||||
 | 
					            "in": "path",
 | 
				
			||||||
 | 
					            "required": true
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "type": "string",
 | 
				
			||||||
 | 
					            "description": "name of the repo to sync",
 | 
				
			||||||
 | 
					            "name": "repo",
 | 
				
			||||||
 | 
					            "in": "path",
 | 
				
			||||||
 | 
					            "required": true
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "responses": {
 | 
				
			||||||
 | 
					          "200": {
 | 
				
			||||||
 | 
					            "$ref": "#/responses/empty"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "400": {
 | 
				
			||||||
 | 
					            "$ref": "#/responses/error"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "403": {
 | 
				
			||||||
 | 
					            "$ref": "#/responses/forbidden"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "/repos/{owner}/{repo}/push_mirrors/{name}": {
 | 
				
			||||||
 | 
					      "get": {
 | 
				
			||||||
 | 
					        "produces": [
 | 
				
			||||||
 | 
					          "application/json"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "tags": [
 | 
				
			||||||
 | 
					          "repository"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "summary": "Get push mirror of the repository by remoteName",
 | 
				
			||||||
 | 
					        "operationId": "repoGetPushMirrorByRemoteName",
 | 
				
			||||||
 | 
					        "parameters": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "type": "string",
 | 
				
			||||||
 | 
					            "description": "owner of the repo",
 | 
				
			||||||
 | 
					            "name": "owner",
 | 
				
			||||||
 | 
					            "in": "path",
 | 
				
			||||||
 | 
					            "required": true
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "type": "string",
 | 
				
			||||||
 | 
					            "description": "name of the repo",
 | 
				
			||||||
 | 
					            "name": "repo",
 | 
				
			||||||
 | 
					            "in": "path",
 | 
				
			||||||
 | 
					            "required": true
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "type": "string",
 | 
				
			||||||
 | 
					            "description": "remote name of push mirror",
 | 
				
			||||||
 | 
					            "name": "name",
 | 
				
			||||||
 | 
					            "in": "path",
 | 
				
			||||||
 | 
					            "required": true
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "responses": {
 | 
				
			||||||
 | 
					          "200": {
 | 
				
			||||||
 | 
					            "$ref": "#/responses/PushMirror"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "400": {
 | 
				
			||||||
 | 
					            "$ref": "#/responses/error"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "403": {
 | 
				
			||||||
 | 
					            "$ref": "#/responses/forbidden"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "delete": {
 | 
				
			||||||
 | 
					        "produces": [
 | 
				
			||||||
 | 
					          "application/json"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "tags": [
 | 
				
			||||||
 | 
					          "repository"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "summary": "deletes a push mirror from a repository by remoteName",
 | 
				
			||||||
 | 
					        "operationId": "repoDeletePushMirror",
 | 
				
			||||||
 | 
					        "parameters": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "type": "string",
 | 
				
			||||||
 | 
					            "description": "owner of the repo",
 | 
				
			||||||
 | 
					            "name": "owner",
 | 
				
			||||||
 | 
					            "in": "path",
 | 
				
			||||||
 | 
					            "required": true
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "type": "string",
 | 
				
			||||||
 | 
					            "description": "name of the repo",
 | 
				
			||||||
 | 
					            "name": "repo",
 | 
				
			||||||
 | 
					            "in": "path",
 | 
				
			||||||
 | 
					            "required": true
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "type": "string",
 | 
				
			||||||
 | 
					            "description": "remote name of the pushMirror",
 | 
				
			||||||
 | 
					            "name": "name",
 | 
				
			||||||
 | 
					            "in": "path",
 | 
				
			||||||
 | 
					            "required": true
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "responses": {
 | 
				
			||||||
 | 
					          "204": {
 | 
				
			||||||
 | 
					            "$ref": "#/responses/empty"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "400": {
 | 
				
			||||||
 | 
					            "$ref": "#/responses/error"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "404": {
 | 
				
			||||||
 | 
					            "$ref": "#/responses/notFound"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "/repos/{owner}/{repo}/raw/{filepath}": {
 | 
					    "/repos/{owner}/{repo}/raw/{filepath}": {
 | 
				
			||||||
      "get": {
 | 
					      "get": {
 | 
				
			||||||
        "produces": [
 | 
					        "produces": [
 | 
				
			||||||
@@ -14441,6 +14668,29 @@
 | 
				
			|||||||
      },
 | 
					      },
 | 
				
			||||||
      "x-go-package": "code.gitea.io/gitea/modules/structs"
 | 
					      "x-go-package": "code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "CreatePushMirrorOption": {
 | 
				
			||||||
 | 
					      "type": "object",
 | 
				
			||||||
 | 
					      "title": "CreatePushMirrorOption represents need information to create a push mirror of a repository.",
 | 
				
			||||||
 | 
					      "properties": {
 | 
				
			||||||
 | 
					        "interval": {
 | 
				
			||||||
 | 
					          "type": "string",
 | 
				
			||||||
 | 
					          "x-go-name": "Interval"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "remote_address": {
 | 
				
			||||||
 | 
					          "type": "string",
 | 
				
			||||||
 | 
					          "x-go-name": "RemoteAddress"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "remote_password": {
 | 
				
			||||||
 | 
					          "type": "string",
 | 
				
			||||||
 | 
					          "x-go-name": "RemotePassword"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "remote_username": {
 | 
				
			||||||
 | 
					          "type": "string",
 | 
				
			||||||
 | 
					          "x-go-name": "RemoteUsername"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "x-go-package": "code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "CreateReleaseOption": {
 | 
					    "CreateReleaseOption": {
 | 
				
			||||||
      "description": "CreateReleaseOption options when creating a release",
 | 
					      "description": "CreateReleaseOption options when creating a release",
 | 
				
			||||||
      "type": "object",
 | 
					      "type": "object",
 | 
				
			||||||
@@ -17516,6 +17766,41 @@
 | 
				
			|||||||
      },
 | 
					      },
 | 
				
			||||||
      "x-go-package": "code.gitea.io/gitea/modules/structs"
 | 
					      "x-go-package": "code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "PushMirror": {
 | 
				
			||||||
 | 
					      "description": "PushMirror represents information of a push mirror",
 | 
				
			||||||
 | 
					      "type": "object",
 | 
				
			||||||
 | 
					      "properties": {
 | 
				
			||||||
 | 
					        "created": {
 | 
				
			||||||
 | 
					          "type": "string",
 | 
				
			||||||
 | 
					          "x-go-name": "CreatedUnix"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "interval": {
 | 
				
			||||||
 | 
					          "type": "string",
 | 
				
			||||||
 | 
					          "x-go-name": "Interval"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "last_error": {
 | 
				
			||||||
 | 
					          "type": "string",
 | 
				
			||||||
 | 
					          "x-go-name": "LastError"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "last_update": {
 | 
				
			||||||
 | 
					          "type": "string",
 | 
				
			||||||
 | 
					          "x-go-name": "LastUpdateUnix"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "remote_address": {
 | 
				
			||||||
 | 
					          "type": "string",
 | 
				
			||||||
 | 
					          "x-go-name": "RemoteAddress"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "remote_name": {
 | 
				
			||||||
 | 
					          "type": "string",
 | 
				
			||||||
 | 
					          "x-go-name": "RemoteName"
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "repo_name": {
 | 
				
			||||||
 | 
					          "type": "string",
 | 
				
			||||||
 | 
					          "x-go-name": "RepoName"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "x-go-package": "code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "Reaction": {
 | 
					    "Reaction": {
 | 
				
			||||||
      "description": "Reaction contain one reaction",
 | 
					      "description": "Reaction contain one reaction",
 | 
				
			||||||
      "type": "object",
 | 
					      "type": "object",
 | 
				
			||||||
@@ -19293,6 +19578,21 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "PushMirror": {
 | 
				
			||||||
 | 
					      "description": "PushMirror",
 | 
				
			||||||
 | 
					      "schema": {
 | 
				
			||||||
 | 
					        "$ref": "#/definitions/PushMirror"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "PushMirrorList": {
 | 
				
			||||||
 | 
					      "description": "PushMirrorList",
 | 
				
			||||||
 | 
					      "schema": {
 | 
				
			||||||
 | 
					        "type": "array",
 | 
				
			||||||
 | 
					        "items": {
 | 
				
			||||||
 | 
					          "$ref": "#/definitions/PushMirror"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "Reaction": {
 | 
					    "Reaction": {
 | 
				
			||||||
      "description": "Reaction",
 | 
					      "description": "Reaction",
 | 
				
			||||||
      "schema": {
 | 
					      "schema": {
 | 
				
			||||||
@@ -19572,7 +19872,7 @@
 | 
				
			|||||||
    "parameterBodies": {
 | 
					    "parameterBodies": {
 | 
				
			||||||
      "description": "parameterBodies",
 | 
					      "description": "parameterBodies",
 | 
				
			||||||
      "schema": {
 | 
					      "schema": {
 | 
				
			||||||
        "$ref": "#/definitions/CreateWikiPageOptions"
 | 
					        "$ref": "#/definitions/CreatePushMirrorOption"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "redirect": {
 | 
					    "redirect": {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user