0
0
mirror of https://github.com/go-gitea/gitea.git synced 2024-12-20 14:48:25 +01:00
gitea/models/migrations/v1_21/v276.go
wxiaoguang 580e21dd2e
Refactor LFS SSH and internal routers (#32473)
Gitea instance keeps reporting a lot of errors like "LFS SSH transfer connection denied, pure SSH protocol is disabled". When starting debugging the problem, there are more problems found. Try to address most of them:

* avoid unnecessary server side error logs (change `fail()` to not log them)
* figure out the broken tests/user2/lfs.git (added comments)
* avoid `migratePushMirrors` failure when a repository doesn't exist (ignore them)
* avoid "Authorization" (internal&lfs) header conflicts, remove the tricky "swapAuth" and use "X-Gitea-Internal-Auth"
* make internal token comparing constant time (it wasn't a serous problem because in a real world it's nearly impossible to timing-attack the token, but good to fix and backport)
* avoid duplicate routers (introduce AddOwnerRepoGitLFSRoutes)
* avoid "internal (private)" routes using session/web context (they should use private context)
* fix incorrect "path" usages (use "filepath")
* fix incorrect mocked route point handling (need to check func nil correctly)
* split some tests from "git general tests" to "git misc tests" (to keep "git_general_test.go" simple)

Still no correct result for Git LFS SSH tests. So the code is kept there
(`tests/integration/git_lfs_ssh_test.go`) and a FIXME explains the details.
2024-11-12 02:38:22 +00:00

183 lines
3.9 KiB
Go

// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v1_21 //nolint
import (
"context"
"fmt"
"path/filepath"
"strings"
"code.gitea.io/gitea/modules/git"
giturl "code.gitea.io/gitea/modules/git/url"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"xorm.io/xorm"
)
func AddRemoteAddressToMirrors(x *xorm.Engine) error {
type Mirror struct {
RemoteAddress string `xorm:"VARCHAR(2048)"`
}
type PushMirror struct {
RemoteAddress string `xorm:"VARCHAR(2048)"`
}
if err := x.Sync(new(Mirror), new(PushMirror)); err != nil {
return err
}
if err := migratePullMirrors(x); err != nil {
return err
}
return migratePushMirrors(x)
}
func migratePullMirrors(x *xorm.Engine) error {
type Mirror struct {
ID int64 `xorm:"pk autoincr"`
RepoID int64 `xorm:"INDEX"`
RemoteAddress string `xorm:"VARCHAR(2048)"`
RepoOwner string
RepoName string
}
sess := x.NewSession()
defer sess.Close()
if err := sess.Begin(); err != nil {
return err
}
limit := setting.Database.IterateBufferSize
if limit <= 0 {
limit = 50
}
start := 0
for {
var mirrors []Mirror
if err := sess.Select("mirror.id, mirror.repo_id, mirror.remote_address, repository.owner_name as repo_owner, repository.name as repo_name").
Join("INNER", "repository", "repository.id = mirror.repo_id").
Limit(limit, start).Find(&mirrors); err != nil {
return err
}
if len(mirrors) == 0 {
break
}
start += len(mirrors)
for _, m := range mirrors {
remoteAddress, err := getRemoteAddress(m.RepoOwner, m.RepoName, "origin")
if err != nil {
return err
}
m.RemoteAddress = remoteAddress
if _, err = sess.ID(m.ID).Cols("remote_address").Update(m); err != nil {
return err
}
}
if start%1000 == 0 { // avoid a too big transaction
if err := sess.Commit(); err != nil {
return err
}
if err := sess.Begin(); err != nil {
return err
}
}
}
return sess.Commit()
}
func migratePushMirrors(x *xorm.Engine) error {
type PushMirror struct {
ID int64 `xorm:"pk autoincr"`
RepoID int64 `xorm:"INDEX"`
RemoteName string
RemoteAddress string `xorm:"VARCHAR(2048)"`
RepoOwner string
RepoName string
}
sess := x.NewSession()
defer sess.Close()
if err := sess.Begin(); err != nil {
return err
}
limit := setting.Database.IterateBufferSize
if limit <= 0 {
limit = 50
}
start := 0
for {
var mirrors []PushMirror
if err := sess.Select("push_mirror.id, push_mirror.repo_id, push_mirror.remote_name, push_mirror.remote_address, repository.owner_name as repo_owner, repository.name as repo_name").
Join("INNER", "repository", "repository.id = push_mirror.repo_id").
Limit(limit, start).Find(&mirrors); err != nil {
return err
}
if len(mirrors) == 0 {
break
}
start += len(mirrors)
for _, m := range mirrors {
remoteAddress, err := getRemoteAddress(m.RepoOwner, m.RepoName, m.RemoteName)
if err != nil {
return err
}
m.RemoteAddress = remoteAddress
if _, err = sess.ID(m.ID).Cols("remote_address").Update(m); err != nil {
return err
}
}
if start%1000 == 0 { // avoid a too big transaction
if err := sess.Commit(); err != nil {
return err
}
if err := sess.Begin(); err != nil {
return err
}
}
}
return sess.Commit()
}
func getRemoteAddress(ownerName, repoName, remoteName string) (string, error) {
repoPath := filepath.Join(setting.RepoRootPath, strings.ToLower(ownerName), strings.ToLower(repoName)+".git")
if exist, _ := util.IsExist(repoPath); !exist {
return "", nil
}
remoteURL, err := git.GetRemoteAddress(context.Background(), repoPath, remoteName)
if err != nil {
return "", fmt.Errorf("get remote %s's address of %s/%s failed: %v", remoteName, ownerName, repoName, err)
}
u, err := giturl.Parse(remoteURL)
if err != nil {
return "", err
}
u.User = nil
return u.String(), nil
}