Move some repository methods from models to modules/repository (#9353)
* Move some repository methods from models to modules/repository * fix test
This commit is contained in:
parent
2904abdc22
commit
7b2ff82d20
|
@ -16,6 +16,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
pwd "code.gitea.io/gitea/modules/password"
|
pwd "code.gitea.io/gitea/modules/password"
|
||||||
|
"code.gitea.io/gitea/modules/repository"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
|
@ -373,7 +374,7 @@ func runRepoSyncReleases(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
log.Trace(" currentNumReleases is %d, running SyncReleasesWithTags", oldnum)
|
log.Trace(" currentNumReleases is %d, running SyncReleasesWithTags", oldnum)
|
||||||
|
|
||||||
if err = models.SyncReleasesWithTags(repo, gitRepo); err != nil {
|
if err = repository.SyncReleasesWithTags(repo, gitRepo); err != nil {
|
||||||
log.Warn(" SyncReleasesWithTags: %v", err)
|
log.Warn(" SyncReleasesWithTags: %v", err)
|
||||||
gitRepo.Close()
|
gitRepo.Close()
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/repository"
|
||||||
|
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
)
|
)
|
||||||
|
@ -44,7 +45,7 @@ func releaseAddColumnIsTagAndSyncTags(x *xorm.Engine) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = models.SyncReleasesWithTags(repo, gitRepo); err != nil {
|
if err = repository.SyncReleasesWithTags(repo, gitRepo); err != nil {
|
||||||
log.Warn("SyncReleasesWithTags: %v", err)
|
log.Warn("SyncReleasesWithTags: %v", err)
|
||||||
}
|
}
|
||||||
gitRepo.Close()
|
gitRepo.Close()
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/git"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/structs"
|
"code.gitea.io/gitea/modules/structs"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
@ -318,49 +317,6 @@ func DeleteReleaseByID(id int64) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// SyncReleasesWithTags synchronizes release table with repository tags
|
|
||||||
func SyncReleasesWithTags(repo *Repository, gitRepo *git.Repository) error {
|
|
||||||
existingRelTags := make(map[string]struct{})
|
|
||||||
opts := FindReleasesOptions{IncludeDrafts: true, IncludeTags: true}
|
|
||||||
for page := 1; ; page++ {
|
|
||||||
rels, err := GetReleasesByRepoID(repo.ID, opts, page, 100)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("GetReleasesByRepoID: %v", err)
|
|
||||||
}
|
|
||||||
if len(rels) == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
for _, rel := range rels {
|
|
||||||
if rel.IsDraft {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
commitID, err := gitRepo.GetTagCommitID(rel.TagName)
|
|
||||||
if err != nil && !git.IsErrNotExist(err) {
|
|
||||||
return fmt.Errorf("GetTagCommitID: %v", err)
|
|
||||||
}
|
|
||||||
if git.IsErrNotExist(err) || commitID != rel.Sha1 {
|
|
||||||
if err := PushUpdateDeleteTag(repo, rel.TagName); err != nil {
|
|
||||||
return fmt.Errorf("PushUpdateDeleteTag: %v", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
existingRelTags[strings.ToLower(rel.TagName)] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tags, err := gitRepo.GetTags()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("GetTags: %v", err)
|
|
||||||
}
|
|
||||||
for _, tagName := range tags {
|
|
||||||
if _, ok := existingRelTags[strings.ToLower(tagName)]; !ok {
|
|
||||||
if err := PushUpdateAddTag(repo, gitRepo, tagName); err != nil {
|
|
||||||
return fmt.Errorf("pushUpdateAddTag: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateReleasesMigrationsByType updates all migrated repositories' releases from gitServiceType to replace originalAuthorID to posterID
|
// UpdateReleasesMigrationsByType updates all migrated repositories' releases from gitServiceType to replace originalAuthorID to posterID
|
||||||
func UpdateReleasesMigrationsByType(gitServiceType structs.GitServiceType, originalAuthorID string, posterID int64) error {
|
func UpdateReleasesMigrationsByType(gitServiceType structs.GitServiceType, originalAuthorID string, posterID int64) error {
|
||||||
_, err := x.Table("release").
|
_, err := x.Table("release").
|
||||||
|
|
161
models/repo.go
161
models/repo.go
|
@ -39,7 +39,6 @@ import (
|
||||||
|
|
||||||
"github.com/mcuadros/go-version"
|
"github.com/mcuadros/go-version"
|
||||||
"github.com/unknwon/com"
|
"github.com/unknwon/com"
|
||||||
ini "gopkg.in/ini.v1"
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -941,25 +940,6 @@ func (repo *Repository) CloneLink() (cl *CloneLink) {
|
||||||
return repo.cloneLink(x, false)
|
return repo.cloneLink(x, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
GitHub, GitLab, Gogs: *.wiki.git
|
|
||||||
BitBucket: *.git/wiki
|
|
||||||
*/
|
|
||||||
var commonWikiURLSuffixes = []string{".wiki.git", ".git/wiki"}
|
|
||||||
|
|
||||||
// wikiRemoteURL returns accessible repository URL for wiki if exists.
|
|
||||||
// Otherwise, it returns an empty string.
|
|
||||||
func wikiRemoteURL(remote string) string {
|
|
||||||
remote = strings.TrimSuffix(remote, ".git")
|
|
||||||
for _, suffix := range commonWikiURLSuffixes {
|
|
||||||
wikiURL := remote + suffix
|
|
||||||
if git.IsRepoURLAccessible(wikiURL) {
|
|
||||||
return wikiURL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckCreateRepository check if could created a repository
|
// CheckCreateRepository check if could created a repository
|
||||||
func CheckCreateRepository(doer, u *User, name string) error {
|
func CheckCreateRepository(doer, u *User, name string) error {
|
||||||
if !doer.CanCreateRepo() {
|
if !doer.CanCreateRepo() {
|
||||||
|
@ -979,118 +959,9 @@ func CheckCreateRepository(doer, u *User, name string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MigrateRepositoryGitData starts migrating git related data after created migrating repository
|
// CreateDelegateHooks creates all the hooks scripts for the repo
|
||||||
func MigrateRepositoryGitData(doer, u *User, repo *Repository, opts api.MigrateRepoOption) (*Repository, error) {
|
func CreateDelegateHooks(repoPath string) error {
|
||||||
repoPath := RepoPath(u.Name, opts.RepoName)
|
return createDelegateHooks(repoPath)
|
||||||
|
|
||||||
if u.IsOrganization() {
|
|
||||||
t, err := u.GetOwnerTeam()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
repo.NumWatches = t.NumMembers
|
|
||||||
} else {
|
|
||||||
repo.NumWatches = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
migrateTimeout := time.Duration(setting.Git.Timeout.Migrate) * time.Second
|
|
||||||
|
|
||||||
var err error
|
|
||||||
if err = os.RemoveAll(repoPath); err != nil {
|
|
||||||
return repo, fmt.Errorf("Failed to remove %s: %v", repoPath, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = git.Clone(opts.CloneAddr, repoPath, git.CloneRepoOptions{
|
|
||||||
Mirror: true,
|
|
||||||
Quiet: true,
|
|
||||||
Timeout: migrateTimeout,
|
|
||||||
}); err != nil {
|
|
||||||
return repo, fmt.Errorf("Clone: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.Wiki {
|
|
||||||
wikiPath := WikiPath(u.Name, opts.RepoName)
|
|
||||||
wikiRemotePath := wikiRemoteURL(opts.CloneAddr)
|
|
||||||
if len(wikiRemotePath) > 0 {
|
|
||||||
if err := os.RemoveAll(wikiPath); err != nil {
|
|
||||||
return repo, fmt.Errorf("Failed to remove %s: %v", wikiPath, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = git.Clone(wikiRemotePath, wikiPath, git.CloneRepoOptions{
|
|
||||||
Mirror: true,
|
|
||||||
Quiet: true,
|
|
||||||
Timeout: migrateTimeout,
|
|
||||||
Branch: "master",
|
|
||||||
}); err != nil {
|
|
||||||
log.Warn("Clone wiki: %v", err)
|
|
||||||
if err := os.RemoveAll(wikiPath); err != nil {
|
|
||||||
return repo, fmt.Errorf("Failed to remove %s: %v", wikiPath, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gitRepo, err := git.OpenRepository(repoPath)
|
|
||||||
if err != nil {
|
|
||||||
return repo, fmt.Errorf("OpenRepository: %v", err)
|
|
||||||
}
|
|
||||||
defer gitRepo.Close()
|
|
||||||
|
|
||||||
repo.IsEmpty, err = gitRepo.IsEmpty()
|
|
||||||
if err != nil {
|
|
||||||
return repo, fmt.Errorf("git.IsEmpty: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !opts.Releases && !repo.IsEmpty {
|
|
||||||
// Try to get HEAD branch and set it as default branch.
|
|
||||||
headBranch, err := gitRepo.GetHEADBranch()
|
|
||||||
if err != nil {
|
|
||||||
return repo, fmt.Errorf("GetHEADBranch: %v", err)
|
|
||||||
}
|
|
||||||
if headBranch != nil {
|
|
||||||
repo.DefaultBranch = headBranch.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = SyncReleasesWithTags(repo, gitRepo); err != nil {
|
|
||||||
log.Error("Failed to synchronize tags to releases for repository: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = repo.UpdateSize(); err != nil {
|
|
||||||
log.Error("Failed to update size for repository: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.Mirror {
|
|
||||||
if _, err = x.InsertOne(&Mirror{
|
|
||||||
RepoID: repo.ID,
|
|
||||||
Interval: setting.Mirror.DefaultInterval,
|
|
||||||
EnablePrune: true,
|
|
||||||
NextUpdateUnix: timeutil.TimeStampNow().AddDuration(setting.Mirror.DefaultInterval),
|
|
||||||
}); err != nil {
|
|
||||||
return repo, fmt.Errorf("InsertOne: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
repo.IsMirror = true
|
|
||||||
err = UpdateRepository(repo, false)
|
|
||||||
} else {
|
|
||||||
repo, err = CleanUpMigrateInfo(repo)
|
|
||||||
}
|
|
||||||
|
|
||||||
return repo, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleanUpMigrateGitConfig removes mirror info which prevents "push --all".
|
|
||||||
// This also removes possible user credentials.
|
|
||||||
func cleanUpMigrateGitConfig(configPath string) error {
|
|
||||||
cfg, err := ini.Load(configPath)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("open config file: %v", err)
|
|
||||||
}
|
|
||||||
cfg.DeleteSection("remote \"origin\"")
|
|
||||||
if err = cfg.SaveToIndent(configPath, "\t"); err != nil {
|
|
||||||
return fmt.Errorf("save config file: %v", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// createDelegateHooks creates all the hooks scripts for the repo
|
// createDelegateHooks creates all the hooks scripts for the repo
|
||||||
|
@ -1132,32 +1003,6 @@ func createDelegateHooks(repoPath string) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CleanUpMigrateInfo finishes migrating repository and/or wiki with things that don't need to be done for mirrors.
|
|
||||||
func CleanUpMigrateInfo(repo *Repository) (*Repository, error) {
|
|
||||||
repoPath := repo.RepoPath()
|
|
||||||
if err := createDelegateHooks(repoPath); err != nil {
|
|
||||||
return repo, fmt.Errorf("createDelegateHooks: %v", err)
|
|
||||||
}
|
|
||||||
if repo.HasWiki() {
|
|
||||||
if err := createDelegateHooks(repo.WikiPath()); err != nil {
|
|
||||||
return repo, fmt.Errorf("createDelegateHooks.(wiki): %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := git.NewCommand("remote", "rm", "origin").RunInDir(repoPath)
|
|
||||||
if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") {
|
|
||||||
return repo, fmt.Errorf("CleanUpMigrateInfo: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if repo.HasWiki() {
|
|
||||||
if err := cleanUpMigrateGitConfig(path.Join(repo.WikiPath(), "config")); err != nil {
|
|
||||||
return repo, fmt.Errorf("cleanUpMigrateGitConfig (wiki): %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return repo, UpdateRepository(repo, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// initRepoCommit temporarily changes with work directory.
|
// initRepoCommit temporarily changes with work directory.
|
||||||
func initRepoCommit(tmpPath string, u *User) (err error) {
|
func initRepoCommit(tmpPath string, u *User) (err error) {
|
||||||
commitTimeStr := time.Now().Format(time.RFC3339)
|
commitTimeStr := time.Now().Format(time.RFC3339)
|
||||||
|
|
|
@ -97,3 +97,9 @@ func MirrorsIterate(f func(idx int, bean interface{}) error) error {
|
||||||
And("next_update_unix!=0").
|
And("next_update_unix!=0").
|
||||||
Iterate(new(Mirror), f)
|
Iterate(new(Mirror), f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InsertMirror inserts a mirror to database
|
||||||
|
func InsertMirror(mirror *Mirror) error {
|
||||||
|
_, err := x.Insert(mirror)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/migrations/base"
|
"code.gitea.io/gitea/modules/migrations/base"
|
||||||
|
"code.gitea.io/gitea/modules/repository"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/structs"
|
"code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
@ -111,7 +112,7 @@ func (g *GiteaLocalUploader) CreateRepo(repo *base.Repository, opts base.Migrate
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err = models.MigrateRepositoryGitData(g.doer, owner, r, structs.MigrateRepoOption{
|
r, err = repository.MigrateRepositoryGitData(g.doer, owner, r, structs.MigrateRepoOption{
|
||||||
RepoName: g.repoName,
|
RepoName: g.repoName,
|
||||||
Description: repo.Description,
|
Description: repo.Description,
|
||||||
OriginalURL: repo.OriginalURL,
|
OriginalURL: repo.OriginalURL,
|
||||||
|
@ -294,7 +295,7 @@ func (g *GiteaLocalUploader) CreateReleases(releases ...*base.Release) error {
|
||||||
|
|
||||||
// SyncTags syncs releases with tags in the database
|
// SyncTags syncs releases with tags in the database
|
||||||
func (g *GiteaLocalUploader) SyncTags() error {
|
func (g *GiteaLocalUploader) SyncTags() error {
|
||||||
return models.SyncReleasesWithTags(g.repo, g.gitRepo)
|
return repository.SyncReleasesWithTags(g.repo, g.gitRepo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateIssues creates issues
|
// CreateIssues creates issues
|
||||||
|
|
|
@ -0,0 +1,223 @@
|
||||||
|
// Copyright 2019 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 repository
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models"
|
||||||
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
"gopkg.in/ini.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
GitHub, GitLab, Gogs: *.wiki.git
|
||||||
|
BitBucket: *.git/wiki
|
||||||
|
*/
|
||||||
|
var commonWikiURLSuffixes = []string{".wiki.git", ".git/wiki"}
|
||||||
|
|
||||||
|
// wikiRemoteURL returns accessible repository URL for wiki if exists.
|
||||||
|
// Otherwise, it returns an empty string.
|
||||||
|
func wikiRemoteURL(remote string) string {
|
||||||
|
remote = strings.TrimSuffix(remote, ".git")
|
||||||
|
for _, suffix := range commonWikiURLSuffixes {
|
||||||
|
wikiURL := remote + suffix
|
||||||
|
if git.IsRepoURLAccessible(wikiURL) {
|
||||||
|
return wikiURL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// MigrateRepositoryGitData starts migrating git related data after created migrating repository
|
||||||
|
func MigrateRepositoryGitData(doer, u *models.User, repo *models.Repository, opts api.MigrateRepoOption) (*models.Repository, error) {
|
||||||
|
repoPath := models.RepoPath(u.Name, opts.RepoName)
|
||||||
|
|
||||||
|
if u.IsOrganization() {
|
||||||
|
t, err := u.GetOwnerTeam()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
repo.NumWatches = t.NumMembers
|
||||||
|
} else {
|
||||||
|
repo.NumWatches = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
migrateTimeout := time.Duration(setting.Git.Timeout.Migrate) * time.Second
|
||||||
|
|
||||||
|
var err error
|
||||||
|
if err = os.RemoveAll(repoPath); err != nil {
|
||||||
|
return repo, fmt.Errorf("Failed to remove %s: %v", repoPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = git.Clone(opts.CloneAddr, repoPath, git.CloneRepoOptions{
|
||||||
|
Mirror: true,
|
||||||
|
Quiet: true,
|
||||||
|
Timeout: migrateTimeout,
|
||||||
|
}); err != nil {
|
||||||
|
return repo, fmt.Errorf("Clone: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.Wiki {
|
||||||
|
wikiPath := models.WikiPath(u.Name, opts.RepoName)
|
||||||
|
wikiRemotePath := wikiRemoteURL(opts.CloneAddr)
|
||||||
|
if len(wikiRemotePath) > 0 {
|
||||||
|
if err := os.RemoveAll(wikiPath); err != nil {
|
||||||
|
return repo, fmt.Errorf("Failed to remove %s: %v", wikiPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = git.Clone(wikiRemotePath, wikiPath, git.CloneRepoOptions{
|
||||||
|
Mirror: true,
|
||||||
|
Quiet: true,
|
||||||
|
Timeout: migrateTimeout,
|
||||||
|
Branch: "master",
|
||||||
|
}); err != nil {
|
||||||
|
log.Warn("Clone wiki: %v", err)
|
||||||
|
if err := os.RemoveAll(wikiPath); err != nil {
|
||||||
|
return repo, fmt.Errorf("Failed to remove %s: %v", wikiPath, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gitRepo, err := git.OpenRepository(repoPath)
|
||||||
|
if err != nil {
|
||||||
|
return repo, fmt.Errorf("OpenRepository: %v", err)
|
||||||
|
}
|
||||||
|
defer gitRepo.Close()
|
||||||
|
|
||||||
|
repo.IsEmpty, err = gitRepo.IsEmpty()
|
||||||
|
if err != nil {
|
||||||
|
return repo, fmt.Errorf("git.IsEmpty: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !opts.Releases && !repo.IsEmpty {
|
||||||
|
// Try to get HEAD branch and set it as default branch.
|
||||||
|
headBranch, err := gitRepo.GetHEADBranch()
|
||||||
|
if err != nil {
|
||||||
|
return repo, fmt.Errorf("GetHEADBranch: %v", err)
|
||||||
|
}
|
||||||
|
if headBranch != nil {
|
||||||
|
repo.DefaultBranch = headBranch.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = SyncReleasesWithTags(repo, gitRepo); err != nil {
|
||||||
|
log.Error("Failed to synchronize tags to releases for repository: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = repo.UpdateSize(); err != nil {
|
||||||
|
log.Error("Failed to update size for repository: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.Mirror {
|
||||||
|
if err = models.InsertMirror(&models.Mirror{
|
||||||
|
RepoID: repo.ID,
|
||||||
|
Interval: setting.Mirror.DefaultInterval,
|
||||||
|
EnablePrune: true,
|
||||||
|
NextUpdateUnix: timeutil.TimeStampNow().AddDuration(setting.Mirror.DefaultInterval),
|
||||||
|
}); err != nil {
|
||||||
|
return repo, fmt.Errorf("InsertOne: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
repo.IsMirror = true
|
||||||
|
err = models.UpdateRepository(repo, false)
|
||||||
|
} else {
|
||||||
|
repo, err = CleanUpMigrateInfo(repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
return repo, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanUpMigrateGitConfig removes mirror info which prevents "push --all".
|
||||||
|
// This also removes possible user credentials.
|
||||||
|
func cleanUpMigrateGitConfig(configPath string) error {
|
||||||
|
cfg, err := ini.Load(configPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("open config file: %v", err)
|
||||||
|
}
|
||||||
|
cfg.DeleteSection("remote \"origin\"")
|
||||||
|
if err = cfg.SaveToIndent(configPath, "\t"); err != nil {
|
||||||
|
return fmt.Errorf("save config file: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CleanUpMigrateInfo finishes migrating repository and/or wiki with things that don't need to be done for mirrors.
|
||||||
|
func CleanUpMigrateInfo(repo *models.Repository) (*models.Repository, error) {
|
||||||
|
repoPath := repo.RepoPath()
|
||||||
|
if err := models.CreateDelegateHooks(repoPath); err != nil {
|
||||||
|
return repo, fmt.Errorf("createDelegateHooks: %v", err)
|
||||||
|
}
|
||||||
|
if repo.HasWiki() {
|
||||||
|
if err := models.CreateDelegateHooks(repo.WikiPath()); err != nil {
|
||||||
|
return repo, fmt.Errorf("createDelegateHooks.(wiki): %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := git.NewCommand("remote", "rm", "origin").RunInDir(repoPath)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") {
|
||||||
|
return repo, fmt.Errorf("CleanUpMigrateInfo: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if repo.HasWiki() {
|
||||||
|
if err := cleanUpMigrateGitConfig(path.Join(repo.WikiPath(), "config")); err != nil {
|
||||||
|
return repo, fmt.Errorf("cleanUpMigrateGitConfig (wiki): %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return repo, models.UpdateRepository(repo, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SyncReleasesWithTags synchronizes release table with repository tags
|
||||||
|
func SyncReleasesWithTags(repo *models.Repository, gitRepo *git.Repository) error {
|
||||||
|
existingRelTags := make(map[string]struct{})
|
||||||
|
opts := models.FindReleasesOptions{IncludeDrafts: true, IncludeTags: true}
|
||||||
|
for page := 1; ; page++ {
|
||||||
|
rels, err := models.GetReleasesByRepoID(repo.ID, opts, page, 100)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("GetReleasesByRepoID: %v", err)
|
||||||
|
}
|
||||||
|
if len(rels) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
for _, rel := range rels {
|
||||||
|
if rel.IsDraft {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
commitID, err := gitRepo.GetTagCommitID(rel.TagName)
|
||||||
|
if err != nil && !git.IsErrNotExist(err) {
|
||||||
|
return fmt.Errorf("GetTagCommitID: %v", err)
|
||||||
|
}
|
||||||
|
if git.IsErrNotExist(err) || commitID != rel.Sha1 {
|
||||||
|
if err := models.PushUpdateDeleteTag(repo, rel.TagName); err != nil {
|
||||||
|
return fmt.Errorf("PushUpdateDeleteTag: %v", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
existingRelTags[strings.ToLower(rel.TagName)] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tags, err := gitRepo.GetTags()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("GetTags: %v", err)
|
||||||
|
}
|
||||||
|
for _, tagName := range tags {
|
||||||
|
if _, ok := existingRelTags[strings.ToLower(tagName)]; !ok {
|
||||||
|
if err := models.PushUpdateAddTag(repo, gitRepo, tagName); err != nil {
|
||||||
|
return fmt.Errorf("pushUpdateAddTag: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/repository"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/modules/validation"
|
"code.gitea.io/gitea/modules/validation"
|
||||||
|
@ -338,7 +339,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
|
||||||
}
|
}
|
||||||
repo.IsMirror = false
|
repo.IsMirror = false
|
||||||
|
|
||||||
if _, err := models.CleanUpMigrateInfo(repo); err != nil {
|
if _, err := repository.CleanUpMigrateInfo(repo); err != nil {
|
||||||
ctx.ServerError("CleanUpMigrateInfo", err)
|
ctx.ServerError("CleanUpMigrateInfo", err)
|
||||||
return
|
return
|
||||||
} else if err = models.DeleteMirrorByRepoID(ctx.Repo.Repository.ID); err != nil {
|
} else if err = models.DeleteMirrorByRepoID(ctx.Repo.Repository.ID); err != nil {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/notification"
|
"code.gitea.io/gitea/modules/notification"
|
||||||
|
"code.gitea.io/gitea/modules/repository"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/sync"
|
"code.gitea.io/gitea/modules/sync"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
@ -207,7 +208,7 @@ func runSync(m *models.Mirror) ([]*mirrorSyncResult, bool) {
|
||||||
log.Error("OpenRepository: %v", err)
|
log.Error("OpenRepository: %v", err)
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
if err = models.SyncReleasesWithTags(m.Repo, gitRepo); err != nil {
|
if err = repository.SyncReleasesWithTags(m.Repo, gitRepo); err != nil {
|
||||||
gitRepo.Close()
|
gitRepo.Close()
|
||||||
log.Error("Failed to synchronize tags to releases for repository: %v", err)
|
log.Error("Failed to synchronize tags to releases for repository: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
"code.gitea.io/gitea/modules/repository"
|
||||||
"code.gitea.io/gitea/modules/structs"
|
"code.gitea.io/gitea/modules/structs"
|
||||||
release_service "code.gitea.io/gitea/services/release"
|
release_service "code.gitea.io/gitea/services/release"
|
||||||
|
|
||||||
|
@ -46,7 +47,7 @@ func TestRelease_MirrorDelete(t *testing.T) {
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
mirror, err := models.MigrateRepositoryGitData(user, user, mirrorRepo, opts)
|
mirror, err := repository.MigrateRepositoryGitData(user, user, mirrorRepo, opts)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
gitRepo, err := git.OpenRepository(repoPath)
|
gitRepo, err := git.OpenRepository(repoPath)
|
||||||
|
|
Loading…
Reference in New Issue