forked from NYANDEV/forgejo
b1e138511b
It is possible that tag commits could be deleted or missing from repos. This causes migration 156 to fail and breaks upgrade. This PR simply logs the failure. Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: 6543 <6543@obermui.de>
160 lines
4.2 KiB
Go
160 lines
4.2 KiB
Go
// Copyright 2020 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 migrations
|
|
|
|
import (
|
|
"fmt"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"code.gitea.io/gitea/modules/git"
|
|
"code.gitea.io/gitea/modules/log"
|
|
"code.gitea.io/gitea/modules/setting"
|
|
|
|
"xorm.io/xorm"
|
|
)
|
|
|
|
// Copy paste from models/repo.go because we cannot import models package
|
|
func repoPath(userName, repoName string) string {
|
|
return filepath.Join(userPath(userName), strings.ToLower(repoName)+".git")
|
|
}
|
|
|
|
func userPath(userName string) string {
|
|
return filepath.Join(setting.RepoRootPath, strings.ToLower(userName))
|
|
}
|
|
|
|
func fixPublisherIDforTagReleases(x *xorm.Engine) error {
|
|
type Release struct {
|
|
ID int64
|
|
RepoID int64
|
|
Sha1 string
|
|
TagName string
|
|
PublisherID int64
|
|
}
|
|
|
|
type Repository struct {
|
|
ID int64
|
|
OwnerID int64
|
|
OwnerName string
|
|
Name string
|
|
}
|
|
|
|
type User struct {
|
|
ID int64
|
|
Name string
|
|
Email string
|
|
}
|
|
|
|
const batchSize = 100
|
|
sess := x.NewSession()
|
|
defer sess.Close()
|
|
|
|
var (
|
|
repo *Repository
|
|
gitRepo *git.Repository
|
|
user *User
|
|
)
|
|
defer func() {
|
|
if gitRepo != nil {
|
|
gitRepo.Close()
|
|
}
|
|
}()
|
|
for start := 0; ; start += batchSize {
|
|
releases := make([]*Release, 0, batchSize)
|
|
|
|
if err := sess.Begin(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := sess.Limit(batchSize, start).
|
|
Where("publisher_id = 0 OR publisher_id is null").
|
|
Asc("repo_id", "id").Where("is_tag=?", true).
|
|
Find(&releases); err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(releases) == 0 {
|
|
break
|
|
}
|
|
|
|
for _, release := range releases {
|
|
if repo == nil || repo.ID != release.RepoID {
|
|
if gitRepo != nil {
|
|
gitRepo.Close()
|
|
gitRepo = nil
|
|
}
|
|
repo = new(Repository)
|
|
has, err := sess.ID(release.RepoID).Get(repo)
|
|
if err != nil {
|
|
log.Error("Error whilst loading repository[%d] for release[%d] with tag name %s", release.RepoID, release.ID, release.TagName)
|
|
return err
|
|
} else if !has {
|
|
log.Warn("Release[%d] is orphaned and refers to non-existing repository %d", release.ID, release.RepoID)
|
|
log.Warn("This release should be deleted")
|
|
continue
|
|
}
|
|
|
|
if repo.OwnerName == "" {
|
|
// v120.go migration may not have been run correctly - we'll just replicate it here
|
|
// because this appears to be a common-ish problem.
|
|
if _, err := sess.Exec("UPDATE repository SET owner_name = (SELECT name FROM `user` WHERE `user`.id = repository.owner_id)"); err != nil {
|
|
log.Error("Error whilst updating repository[%d] owner name", repo.ID)
|
|
return err
|
|
}
|
|
|
|
if _, err := sess.ID(release.RepoID).Get(repo); err != nil {
|
|
log.Error("Error whilst loading repository[%d] for release[%d] with tag name %s", release.RepoID, release.ID, release.TagName)
|
|
return err
|
|
}
|
|
}
|
|
gitRepo, err = git.OpenRepository(repoPath(repo.OwnerName, repo.Name))
|
|
if err != nil {
|
|
log.Error("Error whilst opening git repo for %-v", repo)
|
|
return err
|
|
}
|
|
}
|
|
|
|
commit, err := gitRepo.GetTagCommit(release.TagName)
|
|
if err != nil {
|
|
if git.IsErrNotExist(err) {
|
|
log.Warn("Unable to find commit %s for Tag: %s in %-v. Cannot update publisher ID.", err.(*git.ErrNotExist).ID, release.TagName, repo)
|
|
continue
|
|
}
|
|
log.Error("Error whilst getting commit for Tag: %s in %-v.", release.TagName, repo)
|
|
return fmt.Errorf("GetTagCommit: %v", err)
|
|
}
|
|
|
|
if user == nil || !strings.EqualFold(user.Email, commit.Author.Email) {
|
|
user = new(User)
|
|
_, err = sess.Where("email=?", commit.Author.Email).Get(user)
|
|
if err != nil {
|
|
log.Error("Error whilst getting commit author by email: %s for Tag: %s in %-v.", commit.Author.Email, release.TagName, repo)
|
|
return err
|
|
}
|
|
|
|
user.Email = commit.Author.Email
|
|
}
|
|
|
|
if user.ID <= 0 {
|
|
continue
|
|
}
|
|
|
|
release.PublisherID = user.ID
|
|
if _, err := sess.ID(release.ID).Cols("publisher_id").Update(release); err != nil {
|
|
log.Error("Error whilst updating publisher[%d] for release[%d] with tag name %s", release.PublisherID, release.ID, release.TagName)
|
|
return err
|
|
}
|
|
}
|
|
if gitRepo != nil {
|
|
gitRepo.Close()
|
|
}
|
|
|
|
if err := sess.Commit(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|