Files
gitea/modelmigration/v1_21/v276.go
wxiaoguang fff32e9469 refactor: prepare to decouple the "model migration" package and "models" package (#38533)
Migrations should never use model structs directly, because the model
structs can be different in different releases. e.g. if one migration uses
"User" model, it works in the early releases, then one day, when the
User model changes, the migration breaks because it will use the
new (incorrect) User model, it should only use the old User model.

The same to "modules/structs".

---------

Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: delvh <dev.lh@web.de>
2026-07-20 03:42:02 +00:00

175 lines
3.6 KiB
Go

// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v1_21
import (
"context"
"gitea.dev/modelmigration/base"
repo_model "gitea.dev/models/repo"
"gitea.dev/modules/gitrepo"
"gitea.dev/modules/setting"
)
func AddRemoteAddressToMirrors(x base.EngineMigration) 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 base.EngineMigration) 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 base.EngineMigration) 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) {
ctx := context.Background()
repo := repo_model.CodeRepoByName(ownerName, repoName)
if exist, _ := gitrepo.IsRepositoryExist(ctx, repo); !exist {
return "", nil
}
u, err := gitrepo.GitRemoteGetURL(ctx, repo, remoteName)
if err != nil {
return "", err
}
u.User = nil
return u.String(), nil
}