From c46be2a7f6fe6b0b494c8d29fed9d2cc60c4ea7f Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 26 Jan 2024 12:14:02 +0800 Subject: [PATCH 01/18] Move open git repository method split from git package. For managed repositories, use the method on repository module package. For others, use git.OpenRepository as before --- cmd/admin.go | 2 +- models/issues/pull.go | 76 --- modules/context/api.go | 7 +- modules/context/repo.go | 9 +- modules/contexttest/context_tests.go | 6 +- modules/indexer/stats/db.go | 3 +- modules/repository/branch.go | 4 +- modules/repository/generate.go | 2 +- modules/repository/migrate.go | 363 ++++++++++++ modules/repository/repo.go | 546 +----------------- modules/repository/tag.go | 194 +++++++ modules/repository/wiki.go | 36 ++ routers/api/v1/repo/branch.go | 4 +- routers/api/v1/repo/file.go | 4 +- routers/api/v1/repo/pull.go | 7 +- routers/api/v1/repo/repo.go | 2 +- routers/api/v1/repo/wiki.go | 3 +- routers/private/internal_repo.go | 4 +- routers/web/repo/commit.go | 5 +- routers/web/repo/compare.go | 7 +- routers/web/repo/editor_test.go | 3 +- routers/web/repo/pull.go | 17 +- routers/web/repo/wiki.go | 3 +- routers/web/repo/wiki_test.go | 3 +- routers/web/shared/user/header.go | 3 +- services/actions/notifier_helper.go | 3 +- services/automerge/automerge.go | 7 +- services/convert/pull.go | 9 +- services/doctor/misc.go | 3 +- services/issue/issue.go | 82 ++- services/migrations/gitea_uploader.go | 2 +- services/migrations/gitea_uploader_test.go | 5 +- services/mirror/mirror_pull.go | 4 +- services/mirror/mirror_push.go | 16 +- services/pull/check.go | 3 +- services/pull/merge_rebase.go | 3 +- services/pull/pull.go | 8 +- services/pull/pull_test.go | 5 +- services/release/release_test.go | 10 +- services/repository/adopt.go | 2 +- services/repository/archiver/archiver.go | 3 +- services/repository/branch.go | 2 +- services/repository/create.go | 2 +- services/repository/files/content_test.go | 5 +- services/repository/files/file_test.go | 4 +- services/repository/fork.go | 4 +- services/repository/hooks.go | 5 +- services/repository/lfs.go | 3 +- services/repository/push.go | 8 +- services/wiki/wiki_test.go | 9 +- tests/integration/api_packages_cargo_test.go | 4 +- tests/integration/api_releases_test.go | 5 +- .../integration/api_repo_file_create_test.go | 6 +- .../integration/api_repo_file_update_test.go | 4 +- .../integration/api_repo_files_change_test.go | 4 +- .../api_repo_get_contents_list_test.go | 3 +- .../integration/api_repo_get_contents_test.go | 3 +- tests/integration/api_repo_git_tags_test.go | 3 +- tests/integration/mirror_pull_test.go | 3 +- tests/integration/mirror_push_test.go | 5 +- tests/integration/repofiles_change_test.go | 9 +- 61 files changed, 830 insertions(+), 739 deletions(-) create mode 100644 modules/repository/migrate.go create mode 100644 modules/repository/tag.go create mode 100644 modules/repository/wiki.go diff --git a/cmd/admin.go b/cmd/admin.go index 74bfa5a6c6703..02f6db07fcd6f 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -122,7 +122,7 @@ func runRepoSyncReleases(_ *cli.Context) error { log.Trace("Processing next %d repos of %d", len(repos), count) for _, repo := range repos { log.Trace("Synchronizing repo %s with path %s", repo.FullName(), repo.RepoPath()) - gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(ctx, repo) if err != nil { log.Warn("OpenRepository: %v", err) continue diff --git a/models/issues/pull.go b/models/issues/pull.go index 4ae6e38ae180e..ce170130c4c47 100644 --- a/models/issues/pull.go +++ b/models/issues/pull.go @@ -854,82 +854,6 @@ func MergeBlockedByOutdatedBranch(protectBranch *git_model.ProtectedBranch, pr * return protectBranch.BlockOnOutdatedBranch && pr.CommitsBehind > 0 } -func PullRequestCodeOwnersReview(ctx context.Context, pull *Issue, pr *PullRequest) error { - files := []string{"CODEOWNERS", "docs/CODEOWNERS", ".gitea/CODEOWNERS"} - - if pr.IsWorkInProgress(ctx) { - return nil - } - - if err := pr.LoadBaseRepo(ctx); err != nil { - return err - } - - repo, err := git.OpenRepository(ctx, pr.BaseRepo.RepoPath()) - if err != nil { - return err - } - defer repo.Close() - - branch, err := repo.GetDefaultBranch() - if err != nil { - return err - } - - commit, err := repo.GetBranchCommit(branch) - if err != nil { - return err - } - - var data string - for _, file := range files { - if blob, err := commit.GetBlobByPath(file); err == nil { - data, err = blob.GetBlobContent(setting.UI.MaxDisplayFileSize) - if err == nil { - break - } - } - } - - rules, _ := GetCodeOwnersFromContent(ctx, data) - changedFiles, err := repo.GetFilesChangedBetween(git.BranchPrefix+pr.BaseBranch, pr.GetGitRefName()) - if err != nil { - return err - } - - uniqUsers := make(map[int64]*user_model.User) - uniqTeams := make(map[string]*org_model.Team) - for _, rule := range rules { - for _, f := range changedFiles { - if (rule.Rule.MatchString(f) && !rule.Negative) || (!rule.Rule.MatchString(f) && rule.Negative) { - for _, u := range rule.Users { - uniqUsers[u.ID] = u - } - for _, t := range rule.Teams { - uniqTeams[fmt.Sprintf("%d/%d", t.OrgID, t.ID)] = t - } - } - } - } - - for _, u := range uniqUsers { - if u.ID != pull.Poster.ID { - if _, err := AddReviewRequest(ctx, pull, u, pull.Poster); err != nil { - log.Warn("Failed add assignee user: %s to PR review: %s#%d, error: %s", u.Name, pr.BaseRepo.Name, pr.ID, err) - return err - } - } - } - for _, t := range uniqTeams { - if _, err := AddTeamReviewRequest(ctx, pull, t, pull.Poster); err != nil { - log.Warn("Failed add assignee team: %s to PR review: %s#%d, error: %s", t.Name, pr.BaseRepo.Name, pr.ID, err) - return err - } - } - - return nil -} - // GetCodeOwnersFromContent returns the code owners configuration // Return empty slice if files missing // Return warning messages on parsing errors diff --git a/modules/context/api.go b/modules/context/api.go index f41228ad7674e..cd495c41e8ca0 100644 --- a/modules/context/api.go +++ b/modules/context/api.go @@ -11,13 +11,13 @@ import ( "net/url" "strings" - repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" mc "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/httpcache" "code.gitea.io/gitea/modules/log" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/web" web_types "code.gitea.io/gitea/modules/web/types" @@ -278,10 +278,9 @@ func ReferencesGitRepo(allowEmpty ...bool) func(ctx *APIContext) (cancel context // For API calls. if ctx.Repo.GitRepo == nil { - repoPath := repo_model.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name) - gitRepo, err := git.OpenRepository(ctx, repoPath) + gitRepo, err := repo_module.OpenRepository(ctx, ctx.Repo.Repository) if err != nil { - ctx.Error(http.StatusInternalServerError, "RepoRef Invalid repo "+repoPath, err) + ctx.Error(http.StatusInternalServerError, fmt.Sprintf("Open Repository %v failed", ctx.Repo.Repository.FullName()), err) return cancel } ctx.Repo.GitRepo = gitRepo diff --git a/modules/context/repo.go b/modules/context/repo.go index 8d82be1990da1..46d41a700fe9b 100644 --- a/modules/context/repo.go +++ b/modules/context/repo.go @@ -633,7 +633,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc { return nil } - gitRepo, err := git.OpenRepository(ctx, repo_model.RepoPath(userName, repoName)) + gitRepo, err := repo_module.OpenRepository(ctx, repo) if err != nil { if strings.Contains(err.Error(), "repository does not exist") || strings.Contains(err.Error(), "no such file or directory") { log.Error("Repository %-v has a broken repository on the file system: %s Error: %v", ctx.Repo.Repository, ctx.Repo.Repository.RepoPath(), err) @@ -645,7 +645,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc { } return nil } - ctx.ServerError("RepoAssignment Invalid repo "+repo_model.RepoPath(userName, repoName), err) + ctx.ServerError("RepoAssignment Invalid repo "+repo.FullName(), err) return nil } if ctx.Repo.GitRepo != nil { @@ -920,10 +920,9 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context ) if ctx.Repo.GitRepo == nil { - repoPath := repo_model.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name) - ctx.Repo.GitRepo, err = git.OpenRepository(ctx, repoPath) + ctx.Repo.GitRepo, err = repo_module.OpenRepository(ctx, ctx.Repo.Repository) if err != nil { - ctx.ServerError("RepoRef Invalid repo "+repoPath, err) + ctx.ServerError(fmt.Sprintf("Open Repository %v failed", ctx.Repo.Repository.FullName()), err) return nil } // We opened it, we should close it diff --git a/modules/contexttest/context_tests.go b/modules/contexttest/context_tests.go index 8994c1e451c41..9dafabb30dd2b 100644 --- a/modules/contexttest/context_tests.go +++ b/modules/contexttest/context_tests.go @@ -18,7 +18,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/git" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/templates" "code.gitea.io/gitea/modules/translation" "code.gitea.io/gitea/modules/web/middleware" @@ -107,7 +107,7 @@ func LoadRepoCommit(t *testing.T, ctx gocontext.Context) { assert.FailNow(t, "context is not *context.Context or *context.APIContext") } - gitRepo, err := git.OpenRepository(ctx, repo.Repository.RepoPath()) + gitRepo, err := repo_module.OpenRepository(ctx, repo.Repository) assert.NoError(t, err) defer gitRepo.Close() branch, err := gitRepo.GetHEADBranch() @@ -137,7 +137,7 @@ func LoadUser(t *testing.T, ctx gocontext.Context, userID int64) { func LoadGitRepo(t *testing.T, ctx *context.Context) { assert.NoError(t, ctx.Repo.Repository.LoadOwner(ctx)) var err error - ctx.Repo.GitRepo, err = git.OpenRepository(ctx, ctx.Repo.Repository.RepoPath()) + ctx.Repo.GitRepo, err = repo_module.OpenRepository(ctx, ctx.Repo.Repository) assert.NoError(t, err) } diff --git a/modules/indexer/stats/db.go b/modules/indexer/stats/db.go index 163843b47fa5a..9842e6470be6a 100644 --- a/modules/indexer/stats/db.go +++ b/modules/indexer/stats/db.go @@ -11,6 +11,7 @@ import ( "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" ) @@ -35,7 +36,7 @@ func (db *DBIndexer) Index(id int64) error { return err } - gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(ctx, repo) if err != nil { if err.Error() == "no such file or directory" { return nil diff --git a/modules/repository/branch.go b/modules/repository/branch.go index cd45f162276f3..c82bc719cee75 100644 --- a/modules/repository/branch.go +++ b/modules/repository/branch.go @@ -24,9 +24,9 @@ func SyncRepoBranches(ctx context.Context, repoID, doerID int64) (int64, error) log.Debug("SyncRepoBranches: in Repo[%d:%s]", repo.ID, repo.FullName()) - gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) + gitRepo, err := OpenRepository(ctx, repo) if err != nil { - log.Error("OpenRepository[%s]: %w", repo.RepoPath(), err) + log.Error("OpenRepository[%s]: %w", repo.FullName(), err) return 0, err } defer gitRepo.Close() diff --git a/modules/repository/generate.go b/modules/repository/generate.go index f8478b8c1852a..da2f2987511bc 100644 --- a/modules/repository/generate.go +++ b/modules/repository/generate.go @@ -271,7 +271,7 @@ func generateGitContent(ctx context.Context, repo, templateRepo, generateRepo *r repo.DefaultBranch = templateRepo.DefaultBranch } - gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) + gitRepo, err := OpenRepository(ctx, repo) if err != nil { return fmt.Errorf("openRepository: %w", err) } diff --git a/modules/repository/migrate.go b/modules/repository/migrate.go new file mode 100644 index 0000000000000..7331738c3bdd0 --- /dev/null +++ b/modules/repository/migrate.go @@ -0,0 +1,363 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package repository + +import ( + "context" + "errors" + "fmt" + "io" + "net/http" + "strings" + "time" + + "code.gitea.io/gitea/models/db" + git_model "code.gitea.io/gitea/models/git" + "code.gitea.io/gitea/models/organization" + repo_model "code.gitea.io/gitea/models/repo" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/lfs" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/migration" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/util" +) + +// MigrateRepositoryGitData starts migrating git related data after created migrating repository +func MigrateRepositoryGitData(ctx context.Context, u *user_model.User, + repo *repo_model.Repository, opts migration.MigrateOptions, + httpTransport *http.Transport, +) (*repo_model.Repository, error) { + repoPath := repo_model.RepoPath(u.Name, opts.RepoName) + + if u.IsOrganization() { + t, err := organization.OrgFromUser(u).GetOwnerTeam(ctx) + 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 = util.RemoveAll(repoPath); err != nil { + return repo, fmt.Errorf("Failed to remove %s: %w", repoPath, err) + } + + if err = git.Clone(ctx, opts.CloneAddr, repoPath, git.CloneRepoOptions{ + Mirror: true, + Quiet: true, + Timeout: migrateTimeout, + SkipTLSVerify: setting.Migrations.SkipTLSVerify, + }); err != nil { + if errors.Is(err, context.DeadlineExceeded) { + return repo, fmt.Errorf("Clone timed out. Consider increasing [git.timeout] MIGRATE in app.ini. Underlying Error: %w", err) + } + return repo, fmt.Errorf("Clone: %w", err) + } + + if err := git.WriteCommitGraph(ctx, repoPath); err != nil { + return repo, err + } + + if opts.Wiki { + wikiPath := repo_model.WikiPath(u.Name, opts.RepoName) + wikiRemotePath := WikiRemoteURL(ctx, opts.CloneAddr) + if len(wikiRemotePath) > 0 { + if err := util.RemoveAll(wikiPath); err != nil { + return repo, fmt.Errorf("Failed to remove %s: %w", wikiPath, err) + } + + if err := git.Clone(ctx, wikiRemotePath, wikiPath, git.CloneRepoOptions{ + Mirror: true, + Quiet: true, + Timeout: migrateTimeout, + Branch: "master", + SkipTLSVerify: setting.Migrations.SkipTLSVerify, + }); err != nil { + log.Warn("Clone wiki: %v", err) + if err := util.RemoveAll(wikiPath); err != nil { + return repo, fmt.Errorf("Failed to remove %s: %w", wikiPath, err) + } + } else { + if err := git.WriteCommitGraph(ctx, wikiPath); err != nil { + return repo, err + } + } + } + } + + if repo.OwnerID == u.ID { + repo.Owner = u + } + + if err = CheckDaemonExportOK(ctx, repo); err != nil { + return repo, fmt.Errorf("checkDaemonExportOK: %w", err) + } + + if stdout, _, err := git.NewCommand(ctx, "update-server-info"). + SetDescription(fmt.Sprintf("MigrateRepositoryGitData(git update-server-info): %s", repoPath)). + RunStdString(&git.RunOpts{Dir: repoPath}); err != nil { + log.Error("MigrateRepositoryGitData(git update-server-info) in %v: Stdout: %s\nError: %v", repo, stdout, err) + return repo, fmt.Errorf("error in MigrateRepositoryGitData(git update-server-info): %w", err) + } + + gitRepo, err := git.OpenRepository(ctx, repoPath) + if err != nil { + return repo, fmt.Errorf("OpenRepository: %w", err) + } + defer gitRepo.Close() + + repo.IsEmpty, err = gitRepo.IsEmpty() + if err != nil { + return repo, fmt.Errorf("git.IsEmpty: %w", err) + } + + if !repo.IsEmpty { + if len(repo.DefaultBranch) == 0 { + // Try to get HEAD branch and set it as default branch. + headBranch, err := gitRepo.GetHEADBranch() + if err != nil { + return repo, fmt.Errorf("GetHEADBranch: %w", err) + } + if headBranch != nil { + repo.DefaultBranch = headBranch.Name + } + } + + if _, err := SyncRepoBranchesWithRepo(ctx, repo, gitRepo, u.ID); err != nil { + return repo, fmt.Errorf("SyncRepoBranchesWithRepo: %v", err) + } + + if !opts.Releases { + // note: this will greatly improve release (tag) sync + // for pull-mirrors with many tags + repo.IsMirror = opts.Mirror + if err = SyncReleasesWithTags(ctx, repo, gitRepo); err != nil { + log.Error("Failed to synchronize tags to releases for repository: %v", err) + } + } + + if opts.LFS { + endpoint := lfs.DetermineEndpoint(opts.CloneAddr, opts.LFSEndpoint) + lfsClient := lfs.NewClient(endpoint, httpTransport) + if err = StoreMissingLfsObjectsInRepository(ctx, repo, gitRepo, lfsClient); err != nil { + log.Error("Failed to store missing LFS objects for repository: %v", err) + } + } + } + + ctx, committer, err := db.TxContext(ctx) + if err != nil { + return nil, err + } + defer committer.Close() + + if opts.Mirror { + remoteAddress, err := util.SanitizeURL(opts.CloneAddr) + if err != nil { + return repo, err + } + mirrorModel := repo_model.Mirror{ + RepoID: repo.ID, + Interval: setting.Mirror.DefaultInterval, + EnablePrune: true, + NextUpdateUnix: timeutil.TimeStampNow().AddDuration(setting.Mirror.DefaultInterval), + LFS: opts.LFS, + RemoteAddress: remoteAddress, + } + if opts.LFS { + mirrorModel.LFSEndpoint = opts.LFSEndpoint + } + + if opts.MirrorInterval != "" { + parsedInterval, err := time.ParseDuration(opts.MirrorInterval) + if err != nil { + log.Error("Failed to set Interval: %v", err) + return repo, err + } + if parsedInterval == 0 { + mirrorModel.Interval = 0 + mirrorModel.NextUpdateUnix = 0 + } else if parsedInterval < setting.Mirror.MinInterval { + err := fmt.Errorf("interval %s is set below Minimum Interval of %s", parsedInterval, setting.Mirror.MinInterval) + log.Error("Interval: %s is too frequent", opts.MirrorInterval) + return repo, err + } else { + mirrorModel.Interval = parsedInterval + mirrorModel.NextUpdateUnix = timeutil.TimeStampNow().AddDuration(parsedInterval) + } + } + + if err = repo_model.InsertMirror(ctx, &mirrorModel); err != nil { + return repo, fmt.Errorf("InsertOne: %w", err) + } + + repo.IsMirror = true + if err = UpdateRepository(ctx, repo, false); err != nil { + return nil, err + } + + // this is necessary for sync local tags from remote + configName := fmt.Sprintf("remote.%s.fetch", mirrorModel.GetRemoteName()) + if stdout, _, err := git.NewCommand(ctx, "config"). + AddOptionValues("--add", configName, `+refs/tags/*:refs/tags/*`). + RunStdString(&git.RunOpts{Dir: repoPath}); err != nil { + log.Error("MigrateRepositoryGitData(git config --add +refs/tags/*:refs/tags/*) in %v: Stdout: %s\nError: %v", repo, stdout, err) + return repo, fmt.Errorf("error in MigrateRepositoryGitData(git config --add +refs/tags/*:refs/tags/*): %w", err) + } + } else { + if err = UpdateRepoSize(ctx, repo); err != nil { + log.Error("Failed to update size for repository: %v", err) + } + if repo, err = CleanUpMigrateInfo(ctx, repo); err != nil { + return nil, err + } + } + + return repo, committer.Commit() +} + +// cleanUpMigrateGitConfig removes mirror info which prevents "push --all". +// This also removes possible user credentials. +func cleanUpMigrateGitConfig(ctx context.Context, repoPath string) error { + cmd := git.NewCommand(ctx, "remote", "rm", "origin") + // if the origin does not exist + _, stderr, err := cmd.RunStdString(&git.RunOpts{ + Dir: repoPath, + }) + if err != nil && !strings.HasPrefix(stderr, "fatal: No such remote") { + return err + } + return nil +} + +// CleanUpMigrateInfo finishes migrating repository and/or wiki with things that don't need to be done for mirrors. +func CleanUpMigrateInfo(ctx context.Context, repo *repo_model.Repository) (*repo_model.Repository, error) { + repoPath := repo.RepoPath() + if err := CreateDelegateHooks(repoPath); err != nil { + return repo, fmt.Errorf("createDelegateHooks: %w", err) + } + if repo.HasWiki() { + if err := CreateDelegateHooks(repo.WikiPath()); err != nil { + return repo, fmt.Errorf("createDelegateHooks.(wiki): %w", err) + } + } + + _, _, err := git.NewCommand(ctx, "remote", "rm", "origin").RunStdString(&git.RunOpts{Dir: repoPath}) + if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") { + return repo, fmt.Errorf("CleanUpMigrateInfo: %w", err) + } + + if repo.HasWiki() { + if err := cleanUpMigrateGitConfig(ctx, repo.WikiPath()); err != nil { + return repo, fmt.Errorf("cleanUpMigrateGitConfig (wiki): %w", err) + } + } + + return repo, UpdateRepository(ctx, repo, false) +} + +// StoreMissingLfsObjectsInRepository downloads missing LFS objects +func StoreMissingLfsObjectsInRepository(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, lfsClient lfs.Client) error { + contentStore := lfs.NewContentStore() + + pointerChan := make(chan lfs.PointerBlob) + errChan := make(chan error, 1) + go lfs.SearchPointerBlobs(ctx, gitRepo, pointerChan, errChan) + + downloadObjects := func(pointers []lfs.Pointer) error { + err := lfsClient.Download(ctx, pointers, func(p lfs.Pointer, content io.ReadCloser, objectError error) error { + if objectError != nil { + return objectError + } + + defer content.Close() + + _, err := git_model.NewLFSMetaObject(ctx, repo.ID, p) + if err != nil { + log.Error("Repo[%-v]: Error creating LFS meta object %-v: %v", repo, p, err) + return err + } + + if err := contentStore.Put(p, content); err != nil { + log.Error("Repo[%-v]: Error storing content for LFS meta object %-v: %v", repo, p, err) + if _, err2 := git_model.RemoveLFSMetaObjectByOid(ctx, repo.ID, p.Oid); err2 != nil { + log.Error("Repo[%-v]: Error removing LFS meta object %-v: %v", repo, p, err2) + } + return err + } + return nil + }) + if err != nil { + select { + case <-ctx.Done(): + return nil + default: + } + } + return err + } + + var batch []lfs.Pointer + for pointerBlob := range pointerChan { + meta, err := git_model.GetLFSMetaObjectByOid(ctx, repo.ID, pointerBlob.Oid) + if err != nil && err != git_model.ErrLFSObjectNotExist { + log.Error("Repo[%-v]: Error querying LFS meta object %-v: %v", repo, pointerBlob.Pointer, err) + return err + } + if meta != nil { + log.Trace("Repo[%-v]: Skipping unknown LFS meta object %-v", repo, pointerBlob.Pointer) + continue + } + + log.Trace("Repo[%-v]: LFS object %-v not present in repository", repo, pointerBlob.Pointer) + + exist, err := contentStore.Exists(pointerBlob.Pointer) + if err != nil { + log.Error("Repo[%-v]: Error checking if LFS object %-v exists: %v", repo, pointerBlob.Pointer, err) + return err + } + + if exist { + log.Trace("Repo[%-v]: LFS object %-v already present; creating meta object", repo, pointerBlob.Pointer) + _, err := git_model.NewLFSMetaObject(ctx, repo.ID, pointerBlob.Pointer) + if err != nil { + log.Error("Repo[%-v]: Error creating LFS meta object %-v: %v", repo, pointerBlob.Pointer, err) + return err + } + } else { + if setting.LFS.MaxFileSize > 0 && pointerBlob.Size > setting.LFS.MaxFileSize { + log.Info("Repo[%-v]: LFS object %-v download denied because of LFS_MAX_FILE_SIZE=%d < size %d", repo, pointerBlob.Pointer, setting.LFS.MaxFileSize, pointerBlob.Size) + continue + } + + batch = append(batch, pointerBlob.Pointer) + if len(batch) >= lfsClient.BatchSize() { + if err := downloadObjects(batch); err != nil { + return err + } + batch = nil + } + } + } + if len(batch) > 0 { + if err := downloadObjects(batch); err != nil { + return err + } + } + + err, has := <-errChan + if has { + log.Error("Repo[%-v]: Error enumerating LFS objects for repository: %v", repo, err) + return err + } + + return nil +} diff --git a/modules/repository/repo.go b/modules/repository/repo.go index 5af69763d152e..9e38af1246c3a 100644 --- a/modules/repository/repo.go +++ b/modules/repository/repo.go @@ -5,554 +5,24 @@ package repository import ( "context" - "errors" "fmt" - "io" - "net/http" - "strings" - "time" - "code.gitea.io/gitea/models/db" - git_model "code.gitea.io/gitea/models/git" - "code.gitea.io/gitea/models/organization" repo_model "code.gitea.io/gitea/models/repo" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/lfs" - "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/migration" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" ) -/* -GitHub, GitLab, Gogs: *.wiki.git -BitBucket: *.git/wiki -*/ -var commonWikiURLSuffixes = []string{".wiki.git", ".git/wiki"} +type Repository = git.Repository -// WikiRemoteURL returns accessible repository URL for wiki if exists. -// Otherwise, it returns an empty string. -func WikiRemoteURL(ctx context.Context, remote string) string { - remote = strings.TrimSuffix(remote, ".git") - for _, suffix := range commonWikiURLSuffixes { - wikiURL := remote + suffix - if git.IsRepoURLAccessible(ctx, wikiURL) { - return wikiURL - } - } - return "" +// OpenRepository opens the repository at the given relative path with the provided context. +func OpenRepository(ctx context.Context, repoPath *repo_model.Repository) (*Repository, error) { + return git.OpenRepository(ctx, repoPath.RepoPath()) } -// MigrateRepositoryGitData starts migrating git related data after created migrating repository -func MigrateRepositoryGitData(ctx context.Context, u *user_model.User, - repo *repo_model.Repository, opts migration.MigrateOptions, - httpTransport *http.Transport, -) (*repo_model.Repository, error) { - repoPath := repo_model.RepoPath(u.Name, opts.RepoName) - - if u.IsOrganization() { - t, err := organization.OrgFromUser(u).GetOwnerTeam(ctx) - 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 = util.RemoveAll(repoPath); err != nil { - return repo, fmt.Errorf("Failed to remove %s: %w", repoPath, err) - } - - if err = git.Clone(ctx, opts.CloneAddr, repoPath, git.CloneRepoOptions{ - Mirror: true, - Quiet: true, - Timeout: migrateTimeout, - SkipTLSVerify: setting.Migrations.SkipTLSVerify, - }); err != nil { - if errors.Is(err, context.DeadlineExceeded) { - return repo, fmt.Errorf("Clone timed out. Consider increasing [git.timeout] MIGRATE in app.ini. Underlying Error: %w", err) - } - return repo, fmt.Errorf("Clone: %w", err) - } - - if err := git.WriteCommitGraph(ctx, repoPath); err != nil { - return repo, err - } - - if opts.Wiki { - wikiPath := repo_model.WikiPath(u.Name, opts.RepoName) - wikiRemotePath := WikiRemoteURL(ctx, opts.CloneAddr) - if len(wikiRemotePath) > 0 { - if err := util.RemoveAll(wikiPath); err != nil { - return repo, fmt.Errorf("Failed to remove %s: %w", wikiPath, err) - } - - if err := git.Clone(ctx, wikiRemotePath, wikiPath, git.CloneRepoOptions{ - Mirror: true, - Quiet: true, - Timeout: migrateTimeout, - Branch: "master", - SkipTLSVerify: setting.Migrations.SkipTLSVerify, - }); err != nil { - log.Warn("Clone wiki: %v", err) - if err := util.RemoveAll(wikiPath); err != nil { - return repo, fmt.Errorf("Failed to remove %s: %w", wikiPath, err) - } - } else { - if err := git.WriteCommitGraph(ctx, wikiPath); err != nil { - return repo, err - } - } - } - } - - if repo.OwnerID == u.ID { - repo.Owner = u - } - - if err = CheckDaemonExportOK(ctx, repo); err != nil { - return repo, fmt.Errorf("checkDaemonExportOK: %w", err) - } - - if stdout, _, err := git.NewCommand(ctx, "update-server-info"). - SetDescription(fmt.Sprintf("MigrateRepositoryGitData(git update-server-info): %s", repoPath)). - RunStdString(&git.RunOpts{Dir: repoPath}); err != nil { - log.Error("MigrateRepositoryGitData(git update-server-info) in %v: Stdout: %s\nError: %v", repo, stdout, err) - return repo, fmt.Errorf("error in MigrateRepositoryGitData(git update-server-info): %w", err) - } - - gitRepo, err := git.OpenRepository(ctx, repoPath) - if err != nil { - return repo, fmt.Errorf("OpenRepository: %w", err) - } - defer gitRepo.Close() - - repo.IsEmpty, err = gitRepo.IsEmpty() - if err != nil { - return repo, fmt.Errorf("git.IsEmpty: %w", err) - } - - if !repo.IsEmpty { - if len(repo.DefaultBranch) == 0 { - // Try to get HEAD branch and set it as default branch. - headBranch, err := gitRepo.GetHEADBranch() - if err != nil { - return repo, fmt.Errorf("GetHEADBranch: %w", err) - } - if headBranch != nil { - repo.DefaultBranch = headBranch.Name - } - } - - if _, err := SyncRepoBranchesWithRepo(ctx, repo, gitRepo, u.ID); err != nil { - return repo, fmt.Errorf("SyncRepoBranchesWithRepo: %v", err) - } - - if !opts.Releases { - // note: this will greatly improve release (tag) sync - // for pull-mirrors with many tags - repo.IsMirror = opts.Mirror - if err = SyncReleasesWithTags(ctx, repo, gitRepo); err != nil { - log.Error("Failed to synchronize tags to releases for repository: %v", err) - } - } - - if opts.LFS { - endpoint := lfs.DetermineEndpoint(opts.CloneAddr, opts.LFSEndpoint) - lfsClient := lfs.NewClient(endpoint, httpTransport) - if err = StoreMissingLfsObjectsInRepository(ctx, repo, gitRepo, lfsClient); err != nil { - log.Error("Failed to store missing LFS objects for repository: %v", err) - } - } +// DeleteRepository deletes the repository at the given relative path with the provided context. +func DeleteRepository(ctx context.Context, repo *repo_model.Repository) error { + if err := util.RemoveAll(repo.RepoPath()); err != nil { + return fmt.Errorf("Failed to remove %s: %w", repo.FullName(), err) } - - ctx, committer, err := db.TxContext(ctx) - if err != nil { - return nil, err - } - defer committer.Close() - - if opts.Mirror { - remoteAddress, err := util.SanitizeURL(opts.CloneAddr) - if err != nil { - return repo, err - } - mirrorModel := repo_model.Mirror{ - RepoID: repo.ID, - Interval: setting.Mirror.DefaultInterval, - EnablePrune: true, - NextUpdateUnix: timeutil.TimeStampNow().AddDuration(setting.Mirror.DefaultInterval), - LFS: opts.LFS, - RemoteAddress: remoteAddress, - } - if opts.LFS { - mirrorModel.LFSEndpoint = opts.LFSEndpoint - } - - if opts.MirrorInterval != "" { - parsedInterval, err := time.ParseDuration(opts.MirrorInterval) - if err != nil { - log.Error("Failed to set Interval: %v", err) - return repo, err - } - if parsedInterval == 0 { - mirrorModel.Interval = 0 - mirrorModel.NextUpdateUnix = 0 - } else if parsedInterval < setting.Mirror.MinInterval { - err := fmt.Errorf("interval %s is set below Minimum Interval of %s", parsedInterval, setting.Mirror.MinInterval) - log.Error("Interval: %s is too frequent", opts.MirrorInterval) - return repo, err - } else { - mirrorModel.Interval = parsedInterval - mirrorModel.NextUpdateUnix = timeutil.TimeStampNow().AddDuration(parsedInterval) - } - } - - if err = repo_model.InsertMirror(ctx, &mirrorModel); err != nil { - return repo, fmt.Errorf("InsertOne: %w", err) - } - - repo.IsMirror = true - if err = UpdateRepository(ctx, repo, false); err != nil { - return nil, err - } - - // this is necessary for sync local tags from remote - configName := fmt.Sprintf("remote.%s.fetch", mirrorModel.GetRemoteName()) - if stdout, _, err := git.NewCommand(ctx, "config"). - AddOptionValues("--add", configName, `+refs/tags/*:refs/tags/*`). - RunStdString(&git.RunOpts{Dir: repoPath}); err != nil { - log.Error("MigrateRepositoryGitData(git config --add +refs/tags/*:refs/tags/*) in %v: Stdout: %s\nError: %v", repo, stdout, err) - return repo, fmt.Errorf("error in MigrateRepositoryGitData(git config --add +refs/tags/*:refs/tags/*): %w", err) - } - } else { - if err = UpdateRepoSize(ctx, repo); err != nil { - log.Error("Failed to update size for repository: %v", err) - } - if repo, err = CleanUpMigrateInfo(ctx, repo); err != nil { - return nil, err - } - } - - return repo, committer.Commit() -} - -// cleanUpMigrateGitConfig removes mirror info which prevents "push --all". -// This also removes possible user credentials. -func cleanUpMigrateGitConfig(ctx context.Context, repoPath string) error { - cmd := git.NewCommand(ctx, "remote", "rm", "origin") - // if the origin does not exist - _, stderr, err := cmd.RunStdString(&git.RunOpts{ - Dir: repoPath, - }) - if err != nil && !strings.HasPrefix(stderr, "fatal: No such remote") { - return err - } - return nil -} - -// CleanUpMigrateInfo finishes migrating repository and/or wiki with things that don't need to be done for mirrors. -func CleanUpMigrateInfo(ctx context.Context, repo *repo_model.Repository) (*repo_model.Repository, error) { - repoPath := repo.RepoPath() - if err := CreateDelegateHooks(repoPath); err != nil { - return repo, fmt.Errorf("createDelegateHooks: %w", err) - } - if repo.HasWiki() { - if err := CreateDelegateHooks(repo.WikiPath()); err != nil { - return repo, fmt.Errorf("createDelegateHooks.(wiki): %w", err) - } - } - - _, _, err := git.NewCommand(ctx, "remote", "rm", "origin").RunStdString(&git.RunOpts{Dir: repoPath}) - if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") { - return repo, fmt.Errorf("CleanUpMigrateInfo: %w", err) - } - - if repo.HasWiki() { - if err := cleanUpMigrateGitConfig(ctx, repo.WikiPath()); err != nil { - return repo, fmt.Errorf("cleanUpMigrateGitConfig (wiki): %w", err) - } - } - - return repo, UpdateRepository(ctx, repo, false) -} - -// SyncRepoTags synchronizes releases table with repository tags -func SyncRepoTags(ctx context.Context, repoID int64) error { - repo, err := repo_model.GetRepositoryByID(ctx, repoID) - if err != nil { - return err - } - - gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) - if err != nil { - return err - } - defer gitRepo.Close() - - return SyncReleasesWithTags(ctx, repo, gitRepo) -} - -// SyncReleasesWithTags synchronizes release table with repository tags -func SyncReleasesWithTags(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository) error { - log.Debug("SyncReleasesWithTags: in Repo[%d:%s/%s]", repo.ID, repo.OwnerName, repo.Name) - - // optimized procedure for pull-mirrors which saves a lot of time (in - // particular for repos with many tags). - if repo.IsMirror { - return pullMirrorReleaseSync(ctx, repo, gitRepo) - } - - existingRelTags := make(container.Set[string]) - opts := repo_model.FindReleasesOptions{ - IncludeDrafts: true, - IncludeTags: true, - ListOptions: db.ListOptions{PageSize: 50}, - RepoID: repo.ID, - } - for page := 1; ; page++ { - opts.Page = page - rels, err := db.Find[repo_model.Release](gitRepo.Ctx, opts) - if err != nil { - return fmt.Errorf("unable to GetReleasesByRepoID in Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, 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("unable to GetTagCommitID for %q in Repo[%d:%s/%s]: %w", rel.TagName, repo.ID, repo.OwnerName, repo.Name, err) - } - if git.IsErrNotExist(err) || commitID != rel.Sha1 { - if err := repo_model.PushUpdateDeleteTag(ctx, repo, rel.TagName); err != nil { - return fmt.Errorf("unable to PushUpdateDeleteTag: %q in Repo[%d:%s/%s]: %w", rel.TagName, repo.ID, repo.OwnerName, repo.Name, err) - } - } else { - existingRelTags.Add(strings.ToLower(rel.TagName)) - } - } - } - - _, err := gitRepo.WalkReferences(git.ObjectTag, 0, 0, func(sha1, refname string) error { - tagName := strings.TrimPrefix(refname, git.TagPrefix) - if existingRelTags.Contains(strings.ToLower(tagName)) { - return nil - } - - if err := PushUpdateAddTag(ctx, repo, gitRepo, tagName, sha1, refname); err != nil { - return fmt.Errorf("unable to PushUpdateAddTag: %q to Repo[%d:%s/%s]: %w", tagName, repo.ID, repo.OwnerName, repo.Name, err) - } - - return nil - }) - return err -} - -// PushUpdateAddTag must be called for any push actions to add tag -func PushUpdateAddTag(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, tagName, sha1, refname string) error { - tag, err := gitRepo.GetTagWithID(sha1, tagName) - if err != nil { - return fmt.Errorf("unable to GetTag: %w", err) - } - commit, err := tag.Commit(gitRepo) - if err != nil { - return fmt.Errorf("unable to get tag Commit: %w", err) - } - - sig := tag.Tagger - if sig == nil { - sig = commit.Author - } - if sig == nil { - sig = commit.Committer - } - - var author *user_model.User - createdAt := time.Unix(1, 0) - - if sig != nil { - author, err = user_model.GetUserByEmail(ctx, sig.Email) - if err != nil && !user_model.IsErrUserNotExist(err) { - return fmt.Errorf("unable to GetUserByEmail for %q: %w", sig.Email, err) - } - createdAt = sig.When - } - - commitsCount, err := commit.CommitsCount() - if err != nil { - return fmt.Errorf("unable to get CommitsCount: %w", err) - } - - rel := repo_model.Release{ - RepoID: repo.ID, - TagName: tagName, - LowerTagName: strings.ToLower(tagName), - Sha1: commit.ID.String(), - NumCommits: commitsCount, - CreatedUnix: timeutil.TimeStamp(createdAt.Unix()), - IsTag: true, - } - if author != nil { - rel.PublisherID = author.ID - } - - return repo_model.SaveOrUpdateTag(ctx, repo, &rel) -} - -// StoreMissingLfsObjectsInRepository downloads missing LFS objects -func StoreMissingLfsObjectsInRepository(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, lfsClient lfs.Client) error { - contentStore := lfs.NewContentStore() - - pointerChan := make(chan lfs.PointerBlob) - errChan := make(chan error, 1) - go lfs.SearchPointerBlobs(ctx, gitRepo, pointerChan, errChan) - - downloadObjects := func(pointers []lfs.Pointer) error { - err := lfsClient.Download(ctx, pointers, func(p lfs.Pointer, content io.ReadCloser, objectError error) error { - if objectError != nil { - return objectError - } - - defer content.Close() - - _, err := git_model.NewLFSMetaObject(ctx, repo.ID, p) - if err != nil { - log.Error("Repo[%-v]: Error creating LFS meta object %-v: %v", repo, p, err) - return err - } - - if err := contentStore.Put(p, content); err != nil { - log.Error("Repo[%-v]: Error storing content for LFS meta object %-v: %v", repo, p, err) - if _, err2 := git_model.RemoveLFSMetaObjectByOid(ctx, repo.ID, p.Oid); err2 != nil { - log.Error("Repo[%-v]: Error removing LFS meta object %-v: %v", repo, p, err2) - } - return err - } - return nil - }) - if err != nil { - select { - case <-ctx.Done(): - return nil - default: - } - } - return err - } - - var batch []lfs.Pointer - for pointerBlob := range pointerChan { - meta, err := git_model.GetLFSMetaObjectByOid(ctx, repo.ID, pointerBlob.Oid) - if err != nil && err != git_model.ErrLFSObjectNotExist { - log.Error("Repo[%-v]: Error querying LFS meta object %-v: %v", repo, pointerBlob.Pointer, err) - return err - } - if meta != nil { - log.Trace("Repo[%-v]: Skipping unknown LFS meta object %-v", repo, pointerBlob.Pointer) - continue - } - - log.Trace("Repo[%-v]: LFS object %-v not present in repository", repo, pointerBlob.Pointer) - - exist, err := contentStore.Exists(pointerBlob.Pointer) - if err != nil { - log.Error("Repo[%-v]: Error checking if LFS object %-v exists: %v", repo, pointerBlob.Pointer, err) - return err - } - - if exist { - log.Trace("Repo[%-v]: LFS object %-v already present; creating meta object", repo, pointerBlob.Pointer) - _, err := git_model.NewLFSMetaObject(ctx, repo.ID, pointerBlob.Pointer) - if err != nil { - log.Error("Repo[%-v]: Error creating LFS meta object %-v: %v", repo, pointerBlob.Pointer, err) - return err - } - } else { - if setting.LFS.MaxFileSize > 0 && pointerBlob.Size > setting.LFS.MaxFileSize { - log.Info("Repo[%-v]: LFS object %-v download denied because of LFS_MAX_FILE_SIZE=%d < size %d", repo, pointerBlob.Pointer, setting.LFS.MaxFileSize, pointerBlob.Size) - continue - } - - batch = append(batch, pointerBlob.Pointer) - if len(batch) >= lfsClient.BatchSize() { - if err := downloadObjects(batch); err != nil { - return err - } - batch = nil - } - } - } - if len(batch) > 0 { - if err := downloadObjects(batch); err != nil { - return err - } - } - - err, has := <-errChan - if has { - log.Error("Repo[%-v]: Error enumerating LFS objects for repository: %v", repo, err) - return err - } - - return nil -} - -// pullMirrorReleaseSync is a pull-mirror specific tag<->release table -// synchronization which overwrites all Releases from the repository tags. This -// can be relied on since a pull-mirror is always identical to its -// upstream. Hence, after each sync we want the pull-mirror release set to be -// identical to the upstream tag set. This is much more efficient for -// repositories like https://github.com/vim/vim (with over 13000 tags). -func pullMirrorReleaseSync(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository) error { - log.Trace("pullMirrorReleaseSync: rebuilding releases for pull-mirror Repo[%d:%s/%s]", repo.ID, repo.OwnerName, repo.Name) - tags, numTags, err := gitRepo.GetTagInfos(0, 0) - if err != nil { - return fmt.Errorf("unable to GetTagInfos in pull-mirror Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, err) - } - err = db.WithTx(ctx, func(ctx context.Context) error { - // - // clear out existing releases - // - if _, err := db.DeleteByBean(ctx, &repo_model.Release{RepoID: repo.ID}); err != nil { - return fmt.Errorf("unable to clear releases for pull-mirror Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, err) - } - // - // make release set identical to upstream tags - // - for _, tag := range tags { - release := repo_model.Release{ - RepoID: repo.ID, - TagName: tag.Name, - LowerTagName: strings.ToLower(tag.Name), - Sha1: tag.Object.String(), - // NOTE: ignored, since NumCommits are unused - // for pull-mirrors (only relevant when - // displaying releases, IsTag: false) - NumCommits: -1, - CreatedUnix: timeutil.TimeStamp(tag.Tagger.When.Unix()), - IsTag: true, - } - if err := db.Insert(ctx, release); err != nil { - return fmt.Errorf("unable insert tag %s for pull-mirror Repo[%d:%s/%s]: %w", tag.Name, repo.ID, repo.OwnerName, repo.Name, err) - } - } - return nil - }) - if err != nil { - return fmt.Errorf("unable to rebuild release table for pull-mirror Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, err) - } - - log.Trace("pullMirrorReleaseSync: done rebuilding %d releases", numTags) return nil } diff --git a/modules/repository/tag.go b/modules/repository/tag.go new file mode 100644 index 0000000000000..e51197d883184 --- /dev/null +++ b/modules/repository/tag.go @@ -0,0 +1,194 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package repository + +import ( + "context" + "fmt" + "strings" + "time" + + "code.gitea.io/gitea/models/db" + repo_model "code.gitea.io/gitea/models/repo" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/container" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/timeutil" +) + +// SyncRepoTags synchronizes releases table with repository tags +func SyncRepoTags(ctx context.Context, repoID int64) error { + repo, err := repo_model.GetRepositoryByID(ctx, repoID) + if err != nil { + return err + } + + gitRepo, err := OpenRepository(ctx, repo) + if err != nil { + return err + } + defer gitRepo.Close() + + return SyncReleasesWithTags(ctx, repo, gitRepo) +} + +// SyncReleasesWithTags synchronizes release table with repository tags +func SyncReleasesWithTags(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository) error { + log.Debug("SyncReleasesWithTags: in Repo[%d:%s/%s]", repo.ID, repo.OwnerName, repo.Name) + + // optimized procedure for pull-mirrors which saves a lot of time (in + // particular for repos with many tags). + if repo.IsMirror { + return pullMirrorReleaseSync(ctx, repo, gitRepo) + } + + existingRelTags := make(container.Set[string]) + opts := repo_model.FindReleasesOptions{ + IncludeDrafts: true, + IncludeTags: true, + ListOptions: db.ListOptions{PageSize: 50}, + RepoID: repo.ID, + } + for page := 1; ; page++ { + opts.Page = page + rels, err := db.Find[repo_model.Release](gitRepo.Ctx, opts) + if err != nil { + return fmt.Errorf("unable to GetReleasesByRepoID in Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, 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("unable to GetTagCommitID for %q in Repo[%d:%s/%s]: %w", rel.TagName, repo.ID, repo.OwnerName, repo.Name, err) + } + if git.IsErrNotExist(err) || commitID != rel.Sha1 { + if err := repo_model.PushUpdateDeleteTag(ctx, repo, rel.TagName); err != nil { + return fmt.Errorf("unable to PushUpdateDeleteTag: %q in Repo[%d:%s/%s]: %w", rel.TagName, repo.ID, repo.OwnerName, repo.Name, err) + } + } else { + existingRelTags.Add(strings.ToLower(rel.TagName)) + } + } + } + + _, err := gitRepo.WalkReferences(git.ObjectTag, 0, 0, func(sha1, refname string) error { + tagName := strings.TrimPrefix(refname, git.TagPrefix) + if existingRelTags.Contains(strings.ToLower(tagName)) { + return nil + } + + if err := PushUpdateAddTag(ctx, repo, gitRepo, tagName, sha1, refname); err != nil { + return fmt.Errorf("unable to PushUpdateAddTag: %q to Repo[%d:%s/%s]: %w", tagName, repo.ID, repo.OwnerName, repo.Name, err) + } + + return nil + }) + return err +} + +// PushUpdateAddTag must be called for any push actions to add tag +func PushUpdateAddTag(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, tagName, sha1, refname string) error { + tag, err := gitRepo.GetTagWithID(sha1, tagName) + if err != nil { + return fmt.Errorf("unable to GetTag: %w", err) + } + commit, err := tag.Commit(gitRepo) + if err != nil { + return fmt.Errorf("unable to get tag Commit: %w", err) + } + + sig := tag.Tagger + if sig == nil { + sig = commit.Author + } + if sig == nil { + sig = commit.Committer + } + + var author *user_model.User + createdAt := time.Unix(1, 0) + + if sig != nil { + author, err = user_model.GetUserByEmail(ctx, sig.Email) + if err != nil && !user_model.IsErrUserNotExist(err) { + return fmt.Errorf("unable to GetUserByEmail for %q: %w", sig.Email, err) + } + createdAt = sig.When + } + + commitsCount, err := commit.CommitsCount() + if err != nil { + return fmt.Errorf("unable to get CommitsCount: %w", err) + } + + rel := repo_model.Release{ + RepoID: repo.ID, + TagName: tagName, + LowerTagName: strings.ToLower(tagName), + Sha1: commit.ID.String(), + NumCommits: commitsCount, + CreatedUnix: timeutil.TimeStamp(createdAt.Unix()), + IsTag: true, + } + if author != nil { + rel.PublisherID = author.ID + } + + return repo_model.SaveOrUpdateTag(ctx, repo, &rel) +} + +// pullMirrorReleaseSync is a pull-mirror specific tag<->release table +// synchronization which overwrites all Releases from the repository tags. This +// can be relied on since a pull-mirror is always identical to its +// upstream. Hence, after each sync we want the pull-mirror release set to be +// identical to the upstream tag set. This is much more efficient for +// repositories like https://github.com/vim/vim (with over 13000 tags). +func pullMirrorReleaseSync(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository) error { + log.Trace("pullMirrorReleaseSync: rebuilding releases for pull-mirror Repo[%d:%s/%s]", repo.ID, repo.OwnerName, repo.Name) + tags, numTags, err := gitRepo.GetTagInfos(0, 0) + if err != nil { + return fmt.Errorf("unable to GetTagInfos in pull-mirror Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, err) + } + err = db.WithTx(ctx, func(ctx context.Context) error { + // + // clear out existing releases + // + if _, err := db.DeleteByBean(ctx, &repo_model.Release{RepoID: repo.ID}); err != nil { + return fmt.Errorf("unable to clear releases for pull-mirror Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, err) + } + // + // make release set identical to upstream tags + // + for _, tag := range tags { + release := repo_model.Release{ + RepoID: repo.ID, + TagName: tag.Name, + LowerTagName: strings.ToLower(tag.Name), + Sha1: tag.Object.String(), + // NOTE: ignored, since NumCommits are unused + // for pull-mirrors (only relevant when + // displaying releases, IsTag: false) + NumCommits: -1, + CreatedUnix: timeutil.TimeStamp(tag.Tagger.When.Unix()), + IsTag: true, + } + if err := db.Insert(ctx, release); err != nil { + return fmt.Errorf("unable insert tag %s for pull-mirror Repo[%d:%s/%s]: %w", tag.Name, repo.ID, repo.OwnerName, repo.Name, err) + } + } + return nil + }) + if err != nil { + return fmt.Errorf("unable to rebuild release table for pull-mirror Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, err) + } + + log.Trace("pullMirrorReleaseSync: done rebuilding %d releases", numTags) + return nil +} diff --git a/modules/repository/wiki.go b/modules/repository/wiki.go new file mode 100644 index 0000000000000..65a7b676ffa23 --- /dev/null +++ b/modules/repository/wiki.go @@ -0,0 +1,36 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package repository + +import ( + "context" + "strings" + + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/modules/git" +) + +/* +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(ctx context.Context, remote string) string { + remote = strings.TrimSuffix(remote, ".git") + for _, suffix := range commonWikiURLSuffixes { + wikiURL := remote + suffix + if git.IsRepoURLAccessible(ctx, wikiURL) { + return wikiURL + } + } + return "" +} + +// OpenWikiRepository opens the repository at the given relative path with the provided context. +func OpenWikiRepository(ctx context.Context, repoPath *repo_model.Repository) (*Repository, error) { + return git.OpenRepository(ctx, repoPath.WikiPath()) +} diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index edbfbcc568bad..5697641303d0f 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -643,7 +643,7 @@ func CreateBranchProtection(ctx *context.APIContext) { } else { if !isPlainRule { if ctx.Repo.GitRepo == nil { - ctx.Repo.GitRepo, err = git.OpenRepository(ctx, ctx.Repo.Repository.RepoPath()) + ctx.Repo.GitRepo, err = repo_module.OpenRepository(ctx, ctx.Repo.Repository) if err != nil { ctx.Error(http.StatusInternalServerError, "OpenRepository", err) return @@ -920,7 +920,7 @@ func EditBranchProtection(ctx *context.APIContext) { } else { if !isPlainRule { if ctx.Repo.GitRepo == nil { - ctx.Repo.GitRepo, err = git.OpenRepository(ctx, ctx.Repo.Repository.RepoPath()) + ctx.Repo.GitRepo, err = repo_module.OpenRepository(ctx, ctx.Repo.Repository) if err != nil { ctx.Error(http.StatusInternalServerError, "OpenRepository", err) return diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go index 94e634461c278..bc992404f746a 100644 --- a/routers/api/v1/repo/file.go +++ b/routers/api/v1/repo/file.go @@ -24,6 +24,7 @@ import ( "code.gitea.io/gitea/modules/httpcache" "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/storage" api "code.gitea.io/gitea/modules/structs" @@ -279,9 +280,8 @@ func GetArchive(ctx *context.APIContext) { // "404": // "$ref": "#/responses/notFound" - repoPath := repo_model.RepoPath(ctx.Params(":username"), ctx.Params(":reponame")) if ctx.Repo.GitRepo == nil { - gitRepo, err := git.OpenRepository(ctx, repoPath) + gitRepo, err := repo_module.OpenRepository(ctx, ctx.Repo.Repository) if err != nil { ctx.Error(http.StatusInternalServerError, "OpenRepository", err) return diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index b1cb7011f1d4b..a67f9479e4fc3 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -24,6 +24,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/timeutil" @@ -906,9 +907,9 @@ func MergePullRequest(ctx *context.APIContext) { if ctx.Repo != nil && ctx.Repo.Repository != nil && ctx.Repo.Repository.ID == pr.HeadRepoID && ctx.Repo.GitRepo != nil { headRepo = ctx.Repo.GitRepo } else { - headRepo, err = git.OpenRepository(ctx, pr.HeadRepo.RepoPath()) + headRepo, err = repo_module.OpenRepository(ctx, pr.HeadRepo) if err != nil { - ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.HeadRepo.RepoPath()), err) + ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.HeadRepo.FullName()), err) return } defer headRepo.Close() @@ -1004,7 +1005,7 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) headRepo = ctx.Repo.Repository headGitRepo = ctx.Repo.GitRepo } else { - headGitRepo, err = git.OpenRepository(ctx, repo_model.RepoPath(headUser.Name, headRepo.Name)) + headGitRepo, err = repo_module.OpenRepository(ctx, headRepo) if err != nil { ctx.Error(http.StatusInternalServerError, "OpenRepository", err) return nil, nil, nil, nil, "", "" diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 436b83adf2b35..6f975fce9fbeb 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -718,7 +718,7 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err if ctx.Repo.GitRepo == nil && !repo.IsEmpty { var err error - ctx.Repo.GitRepo, err = git.OpenRepository(ctx, ctx.Repo.Repository.RepoPath()) + ctx.Repo.GitRepo, err = repo_module.OpenRepository(ctx, ctx.Repo.Repository) if err != nil { ctx.Error(http.StatusInternalServerError, "Unable to OpenRepository", err) return err diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 8e5ecce310e3e..769bfd778b44e 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -12,6 +12,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" @@ -475,7 +476,7 @@ func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error) // findWikiRepoCommit opens the wiki repo and returns the latest commit, writing to context on error. // The caller is responsible for closing the returned repo again func findWikiRepoCommit(ctx *context.APIContext) (*git.Repository, *git.Commit) { - wikiRepo, err := git.OpenRepository(ctx, ctx.Repo.Repository.WikiPath()) + wikiRepo, err := repo_module.OpenWikiRepository(ctx, ctx.Repo.Repository) if err != nil { if git.IsErrNotExist(err) || err.Error() == "no such file or directory" { diff --git a/routers/private/internal_repo.go b/routers/private/internal_repo.go index 5e7e82b03c961..0dec1fbcb5697 100644 --- a/routers/private/internal_repo.go +++ b/routers/private/internal_repo.go @@ -10,9 +10,9 @@ import ( repo_model "code.gitea.io/gitea/models/repo" gitea_context "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/private" + repo_module "code.gitea.io/gitea/modules/repository" ) // This file contains common functions relating to setting the Repository for the internal routes @@ -28,7 +28,7 @@ func RepoAssignment(ctx *gitea_context.PrivateContext) context.CancelFunc { return nil } - gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(ctx, repo) if err != nil { log.Error("Failed to open repository: %s/%s Error: %v", ownerName, repoName, err) ctx.JSON(http.StatusInternalServerError, private.Response{ diff --git a/routers/web/repo/commit.go b/routers/web/repo/commit.go index abb39caa5753e..8ff428dbb197f 100644 --- a/routers/web/repo/commit.go +++ b/routers/web/repo/commit.go @@ -24,6 +24,7 @@ import ( "code.gitea.io/gitea/modules/gitgraph" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/services/gitdiff" @@ -279,7 +280,7 @@ func Diff(ctx *context.Context) { ) if ctx.Data["PageIsWiki"] != nil { - gitRepo, err = git.OpenRepository(ctx, ctx.Repo.Repository.WikiPath()) + gitRepo, err = repo_module.OpenWikiRepository(ctx, ctx.Repo.Repository) if err != nil { ctx.ServerError("Repo.GitRepo.GetCommit", err) return @@ -404,7 +405,7 @@ func Diff(ctx *context.Context) { func RawDiff(ctx *context.Context) { var gitRepo *git.Repository if ctx.Data["PageIsWiki"] != nil { - wikiRepo, err := git.OpenRepository(ctx, ctx.Repo.Repository.WikiPath()) + wikiRepo, err := repo_module.OpenWikiRepository(ctx, ctx.Repo.Repository) if err != nil { ctx.ServerError("OpenRepository", err) return diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index 042b8ed692acf..c62a34289fd60 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -30,6 +30,7 @@ import ( "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/typesniffer" @@ -408,7 +409,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo { ci.HeadRepo = ctx.Repo.Repository ci.HeadGitRepo = ctx.Repo.GitRepo } else if has { - ci.HeadGitRepo, err = git.OpenRepository(ctx, ci.HeadRepo.RepoPath()) + ci.HeadGitRepo, err = repo_module.OpenRepository(ctx, ci.HeadRepo) if err != nil { ctx.ServerError("OpenRepository", err) return nil @@ -688,7 +689,7 @@ func PrepareCompareDiff( } func getBranchesAndTagsForRepo(ctx gocontext.Context, repo *repo_model.Repository) (branches, tags []string, err error) { - gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(ctx, repo) if err != nil { return nil, nil, err } @@ -876,7 +877,7 @@ func ExcerptBlob(ctx *context.Context) { gitRepo := ctx.Repo.GitRepo if ctx.FormBool("wiki") { var err error - gitRepo, err = git.OpenRepository(ctx, ctx.Repo.Repository.WikiPath()) + gitRepo, err = repo_module.OpenWikiRepository(ctx, ctx.Repo.Repository) if err != nil { ctx.ServerError("OpenRepository", err) return diff --git a/routers/web/repo/editor_test.go b/routers/web/repo/editor_test.go index 67fb277d5c2b0..ae21bd4e7f36f 100644 --- a/routers/web/repo/editor_test.go +++ b/routers/web/repo/editor_test.go @@ -9,6 +9,7 @@ import ( "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/contexttest" "code.gitea.io/gitea/modules/git" + repo_module "code.gitea.io/gitea/modules/repository" "github.com/stretchr/testify/assert" ) @@ -66,7 +67,7 @@ func TestGetClosestParentWithFiles(t *testing.T) { repo := ctx.Repo.Repository branch := repo.DefaultBranch - gitRepo, _ := git.OpenRepository(git.DefaultContext, repo.RepoPath()) + gitRepo, _ := repo_module.OpenRepository(git.DefaultContext, repo) defer gitRepo.Close() commit, _ := gitRepo.GetBranchCommit(branch) var expectedTreePath string // Should return the root dir, empty string, since there are no subdirs in this repo diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index e36d7092af286..0d96e3f156078 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -31,6 +31,7 @@ import ( "code.gitea.io/gitea/modules/git" issue_template "code.gitea.io/gitea/modules/issue/template" "code.gitea.io/gitea/modules/log" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/upload" @@ -530,7 +531,7 @@ func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.C if pull.BaseRepoID == ctx.Repo.Repository.ID && ctx.Repo.GitRepo != nil { baseGitRepo = ctx.Repo.GitRepo } else { - baseGitRepo, err := git.OpenRepository(ctx, pull.BaseRepo.RepoPath()) + baseGitRepo, err := repo_module.OpenRepository(ctx, pull.BaseRepo) if err != nil { ctx.ServerError("OpenRepository", err) return nil @@ -582,7 +583,7 @@ func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.C var headBranchSha string // HeadRepo may be missing if pull.HeadRepo != nil { - headGitRepo, err := git.OpenRepository(ctx, pull.HeadRepo.RepoPath()) + headGitRepo, err := repo_module.OpenRepository(ctx, pull.HeadRepo) if err != nil { ctx.ServerError("OpenRepository", err) return nil @@ -1314,9 +1315,9 @@ func MergePullRequest(ctx *context.Context) { if ctx.Repo != nil && ctx.Repo.Repository != nil && pr.HeadRepoID == ctx.Repo.Repository.ID && ctx.Repo.GitRepo != nil { headRepo = ctx.Repo.GitRepo } else { - headRepo, err = git.OpenRepository(ctx, pr.HeadRepo.RepoPath()) + headRepo, err = repo_module.OpenRepository(ctx, pr.HeadRepo) if err != nil { - ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.HeadRepo.RepoPath()), err) + ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.HeadRepo.FullName()), err) return } defer headRepo.Close() @@ -1537,9 +1538,9 @@ func CleanUpPullRequest(ctx *context.Context) { gitBaseRepo = ctx.Repo.GitRepo } else { // If not just open it - gitBaseRepo, err = git.OpenRepository(ctx, pr.BaseRepo.RepoPath()) + gitBaseRepo, err = repo_module.OpenRepository(ctx, pr.BaseRepo) if err != nil { - ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.BaseRepo.RepoPath()), err) + ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.BaseRepo.FullName()), err) return } defer gitBaseRepo.Close() @@ -1552,9 +1553,9 @@ func CleanUpPullRequest(ctx *context.Context) { gitRepo = ctx.Repo.GitRepo } else if pr.BaseRepoID != pr.HeadRepoID { // Otherwise just load it up - gitRepo, err = git.OpenRepository(ctx, pr.HeadRepo.RepoPath()) + gitRepo, err = repo_module.OpenRepository(ctx, pr.HeadRepo) if err != nil { - ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.HeadRepo.RepoPath()), err) + ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.HeadRepo.FullName()), err) return } defer gitRepo.Close() diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go index 4e09f046cf856..f665c784fd738 100644 --- a/routers/web/repo/wiki.go +++ b/routers/web/repo/wiki.go @@ -23,6 +23,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/markup/markdown" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" @@ -92,7 +93,7 @@ func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error) } func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, error) { - wikiRepo, err := git.OpenRepository(ctx, ctx.Repo.Repository.WikiPath()) + wikiRepo, err := repo_module.OpenWikiRepository(ctx, ctx.Repo.Repository) if err != nil { ctx.ServerError("OpenRepository", err) return nil, nil, err diff --git a/routers/web/repo/wiki_test.go b/routers/web/repo/wiki_test.go index ae050df967a52..629b2f0248bba 100644 --- a/routers/web/repo/wiki_test.go +++ b/routers/web/repo/wiki_test.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/contexttest" "code.gitea.io/gitea/modules/git" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/services/forms" wiki_service "code.gitea.io/gitea/services/wiki" @@ -26,7 +27,7 @@ const ( ) func wikiEntry(t *testing.T, repo *repo_model.Repository, wikiName wiki_service.WebPath) *git.TreeEntry { - wikiRepo, err := git.OpenRepository(git.DefaultContext, repo.WikiPath()) + wikiRepo, err := repo_module.OpenWikiRepository(git.DefaultContext, repo) assert.NoError(t, err) defer wikiRepo.Close() commit, err := wikiRepo.GetBranchCommit("master") diff --git a/routers/web/shared/user/header.go b/routers/web/shared/user/header.go index 0f8d64e7b24d3..cd99a734e9c72 100644 --- a/routers/web/shared/user/header.go +++ b/routers/web/shared/user/header.go @@ -16,6 +16,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/markup/markdown" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" ) @@ -90,7 +91,7 @@ func FindUserProfileReadme(ctx *context.Context, doer *user_model.User) (profile if err == nil { perm, err := access_model.GetUserRepoPermission(ctx, profileDbRepo, doer) if err == nil && !profileDbRepo.IsEmpty && perm.CanRead(unit.TypeCode) { - if profileGitRepo, err = git.OpenRepository(ctx, profileDbRepo.RepoPath()); err != nil { + if profileGitRepo, err = repo_module.OpenRepository(ctx, profileDbRepo); err != nil { log.Error("FindUserProfileReadme failed to OpenRepository: %v", err) } else { if commit, err := profileGitRepo.GetBranchCommit(profileDbRepo.DefaultBranch); err != nil { diff --git a/services/actions/notifier_helper.go b/services/actions/notifier_helper.go index 2a3ffb76f30d2..5458de1793145 100644 --- a/services/actions/notifier_helper.go +++ b/services/actions/notifier_helper.go @@ -22,6 +22,7 @@ import ( "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" webhook_module "code.gitea.io/gitea/modules/webhook" @@ -128,7 +129,7 @@ func notify(ctx context.Context, input *notifyInput) error { return nil } - gitRepo, err := git.OpenRepository(context.Background(), input.Repo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(context.Background(), input.Repo) if err != nil { return fmt.Errorf("git.OpenRepository: %w", err) } diff --git a/services/automerge/automerge.go b/services/automerge/automerge.go index bf713c44314dd..54cf136a47332 100644 --- a/services/automerge/automerge.go +++ b/services/automerge/automerge.go @@ -21,6 +21,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/queue" + repo_module "code.gitea.io/gitea/modules/repository" pull_service "code.gitea.io/gitea/services/pull" ) @@ -111,7 +112,7 @@ func MergeScheduledPullRequest(ctx context.Context, sha string, repo *repo_model } func getPullRequestsByHeadSHA(ctx context.Context, sha string, repo *repo_model.Repository, filter func(*issues_model.PullRequest) bool) (map[int64]*issues_model.PullRequest, error) { - gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(ctx, repo) if err != nil { return nil, err } @@ -190,7 +191,7 @@ func handlePull(pullID int64, sha string) { return } - headGitRepo, err := git.OpenRepository(ctx, pr.HeadRepo.RepoPath()) + headGitRepo, err := repo_module.OpenRepository(ctx, pr.HeadRepo) if err != nil { log.Error("OpenRepository %-v: %v", pr.HeadRepo, err) return @@ -246,7 +247,7 @@ func handlePull(pullID int64, sha string) { return } - baseGitRepo, err = git.OpenRepository(ctx, pr.BaseRepo.RepoPath()) + baseGitRepo, err = repo_module.OpenRepository(ctx, pr.BaseRepo) if err != nil { log.Error("OpenRepository %-v: %v", pr.BaseRepo, err) return diff --git a/services/convert/pull.go b/services/convert/pull.go index 7eebe20426c31..a12457086517a 100644 --- a/services/convert/pull.go +++ b/services/convert/pull.go @@ -13,6 +13,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" + repo_module "code.gitea.io/gitea/modules/repository" api "code.gitea.io/gitea/modules/structs" ) @@ -101,7 +102,7 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u apiPullRequest.Closed = pr.Issue.ClosedUnix.AsTimePtr() } - gitRepo, err := git.OpenRepository(ctx, pr.BaseRepo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(ctx, pr.BaseRepo) if err != nil { log.Error("OpenRepository[%s]: %v", pr.BaseRepo.RepoPath(), err) return nil @@ -127,7 +128,7 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u } if pr.Flow == issues_model.PullRequestFlowAGit { - gitRepo, err := git.OpenRepository(ctx, pr.BaseRepo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(ctx, pr.BaseRepo) if err != nil { log.Error("OpenRepository[%s]: %v", pr.GetGitRefName(), err) return nil @@ -154,7 +155,7 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u apiPullRequest.Head.RepoID = pr.HeadRepo.ID apiPullRequest.Head.Repository = ToRepo(ctx, pr.HeadRepo, p) - headGitRepo, err := git.OpenRepository(ctx, pr.HeadRepo.RepoPath()) + headGitRepo, err := repo_module.OpenRepository(ctx, pr.HeadRepo) if err != nil { log.Error("OpenRepository[%s]: %v", pr.HeadRepo.RepoPath(), err) return nil @@ -190,7 +191,7 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u } if len(apiPullRequest.Head.Sha) == 0 && len(apiPullRequest.Head.Ref) != 0 { - baseGitRepo, err := git.OpenRepository(ctx, pr.BaseRepo.RepoPath()) + baseGitRepo, err := repo_module.OpenRepository(ctx, pr.BaseRepo) if err != nil { log.Error("OpenRepository[%s]: %v", pr.BaseRepo.RepoPath(), err) return nil diff --git a/services/doctor/misc.go b/services/doctor/misc.go index f0b5966b5440d..ace9f29aa56e2 100644 --- a/services/doctor/misc.go +++ b/services/doctor/misc.go @@ -18,6 +18,7 @@ import ( "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/repository" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" @@ -91,7 +92,7 @@ func checkEnablePushOptions(ctx context.Context, logger log.Logger, autofix bool if err := iterateRepositories(ctx, func(repo *repo_model.Repository) error { numRepos++ - r, err := git.OpenRepository(ctx, repo.RepoPath()) + r, err := repo_module.OpenRepository(ctx, repo) if err != nil { return err } diff --git a/services/issue/issue.go b/services/issue/issue.go index b1f418c32e565..0194d3a353ad8 100644 --- a/services/issue/issue.go +++ b/services/issue/issue.go @@ -10,12 +10,16 @@ import ( activities_model "code.gitea.io/gitea/models/activities" "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" + org_model "code.gitea.io/gitea/models/organization" access_model "code.gitea.io/gitea/models/perm/access" project_model "code.gitea.io/gitea/models/project" repo_model "code.gitea.io/gitea/models/repo" system_model "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" + repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/storage" notify_service "code.gitea.io/gitea/services/notify" ) @@ -48,6 +52,82 @@ func NewIssue(ctx context.Context, repo *repo_model.Repository, issue *issues_mo return nil } +func PullRequestCodeOwnersReview(ctx context.Context, pull *issues_model.Issue, pr *issues_model.PullRequest) error { + files := []string{"CODEOWNERS", "docs/CODEOWNERS", ".gitea/CODEOWNERS"} + + if pr.IsWorkInProgress(ctx) { + return nil + } + + if err := pr.LoadBaseRepo(ctx); err != nil { + return err + } + + repo, err := repo_module.OpenRepository(ctx, pr.BaseRepo) + if err != nil { + return err + } + defer repo.Close() + + branch, err := repo.GetDefaultBranch() + if err != nil { + return err + } + + commit, err := repo.GetBranchCommit(branch) + if err != nil { + return err + } + + var data string + for _, file := range files { + if blob, err := commit.GetBlobByPath(file); err == nil { + data, err = blob.GetBlobContent(setting.UI.MaxDisplayFileSize) + if err == nil { + break + } + } + } + + rules, _ := issues_model.GetCodeOwnersFromContent(ctx, data) + changedFiles, err := repo.GetFilesChangedBetween(git.BranchPrefix+pr.BaseBranch, pr.GetGitRefName()) + if err != nil { + return err + } + + uniqUsers := make(map[int64]*user_model.User) + uniqTeams := make(map[string]*org_model.Team) + for _, rule := range rules { + for _, f := range changedFiles { + if (rule.Rule.MatchString(f) && !rule.Negative) || (!rule.Rule.MatchString(f) && rule.Negative) { + for _, u := range rule.Users { + uniqUsers[u.ID] = u + } + for _, t := range rule.Teams { + uniqTeams[fmt.Sprintf("%d/%d", t.OrgID, t.ID)] = t + } + } + } + } + + for _, u := range uniqUsers { + if u.ID != pull.Poster.ID { + if _, err := issues_model.AddReviewRequest(ctx, pull, u, pull.Poster); err != nil { + log.Warn("Failed add assignee user: %s to PR review: %s#%d, error: %s", u.Name, pr.BaseRepo.Name, pr.ID, err) + return err + } + } + } + for _, t := range uniqTeams { + if _, err := issues_model.AddTeamReviewRequest(ctx, pull, t, pull.Poster); err != nil { + log.Warn("Failed add assignee team: %s to PR review: %s#%d, error: %s", t.Name, pr.BaseRepo.Name, pr.ID, err) + return err + } + } + + return nil +} + // ChangeTitle changes the title of this issue, as the given user. func ChangeTitle(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, title string) error { oldTitle := issue.Title @@ -62,7 +142,7 @@ func ChangeTitle(ctx context.Context, issue *issues_model.Issue, doer *user_mode } if issue.IsPull && issues_model.HasWorkInProgressPrefix(oldTitle) && !issues_model.HasWorkInProgressPrefix(title) { - if err := issues_model.PullRequestCodeOwnersReview(ctx, issue, issue.PullRequest); err != nil { + if err := PullRequestCodeOwnersReview(ctx, issue, issue.PullRequest); err != nil { return err } } diff --git a/services/migrations/gitea_uploader.go b/services/migrations/gitea_uploader.go index 5a4392c66775f..32d9875c190b0 100644 --- a/services/migrations/gitea_uploader.go +++ b/services/migrations/gitea_uploader.go @@ -139,7 +139,7 @@ func (g *GiteaLocalUploader) CreateRepo(repo *base.Repository, opts base.Migrate if err != nil { return err } - g.gitRepo, err = git.OpenRepository(g.ctx, r.RepoPath()) + g.gitRepo, err = repo_module.OpenRepository(g.ctx, r) return err } diff --git a/services/migrations/gitea_uploader_test.go b/services/migrations/gitea_uploader_test.go index 4ec0361dfb467..9593937c3d3b7 100644 --- a/services/migrations/gitea_uploader_test.go +++ b/services/migrations/gitea_uploader_test.go @@ -22,6 +22,7 @@ import ( "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" base "code.gitea.io/gitea/modules/migration" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/modules/util" @@ -249,7 +250,7 @@ func TestGiteaUploadUpdateGitForPullRequest(t *testing.T) { Author: &signature, Message: "Initial Commit", })) - fromGitRepo, err := git.OpenRepository(git.DefaultContext, fromRepo.RepoPath()) + fromGitRepo, err := repo_module.OpenRepository(git.DefaultContext, fromRepo) assert.NoError(t, err) defer fromGitRepo.Close() baseSHA, err := fromGitRepo.GetBranchCommitID(baseRef) @@ -292,7 +293,7 @@ func TestGiteaUploadUpdateGitForPullRequest(t *testing.T) { Author: &signature, Message: "branch2 commit", })) - forkGitRepo, err := git.OpenRepository(git.DefaultContext, forkRepo.RepoPath()) + forkGitRepo, err := repo_module.OpenRepository(git.DefaultContext, forkRepo) assert.NoError(t, err) defer forkGitRepo.Close() forkHeadSHA, err := forkGitRepo.GetBranchCommitID(forkHeadRef) diff --git a/services/mirror/mirror_pull.go b/services/mirror/mirror_pull.go index 6f03e14ab08bd..3baaa50ac4774 100644 --- a/services/mirror/mirror_pull.go +++ b/services/mirror/mirror_pull.go @@ -300,7 +300,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo log.Error("SyncMirrors [repo: %-v]: %v", m.Repo, err) } - gitRepo, err := git.OpenRepository(ctx, repoPath) + gitRepo, err := repo_module.OpenRepository(ctx, m.Repo) if err != nil { log.Error("SyncMirrors [repo: %-v]: failed to OpenRepository: %v", m.Repo, err) return nil, false @@ -453,7 +453,7 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool { log.Trace("SyncMirrors [repo: %-v]: no branches updated", m.Repo) } else { log.Trace("SyncMirrors [repo: %-v]: %d branches updated", m.Repo, len(results)) - gitRepo, err = git.OpenRepository(ctx, m.Repo.RepoPath()) + gitRepo, err = repo_module.OpenRepository(ctx, m.Repo) if err != nil { log.Error("SyncMirrors [repo: %-v]: unable to OpenRepository: %v", m.Repo, err) return false diff --git a/services/mirror/mirror_push.go b/services/mirror/mirror_push.go index b117e79faca96..af968b0973483 100644 --- a/services/mirror/mirror_push.go +++ b/services/mirror/mirror_push.go @@ -19,6 +19,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/repository" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" @@ -131,7 +132,11 @@ func SyncPushMirror(ctx context.Context, mirrorID int64) bool { func runPushSync(ctx context.Context, m *repo_model.PushMirror) error { timeout := time.Duration(setting.Git.Timeout.Mirror) * time.Second - performPush := func(path string) error { + performPush := func(repo *repo_model.Repository, isWiki bool) error { + path := repo.RepoPath() + if isWiki { + path = repo.WikiPath() + } remoteURL, err := git.GetRemoteURL(ctx, path, m.RemoteName) if err != nil { log.Error("GetRemoteAddress(%s) Error %v", path, err) @@ -141,7 +146,7 @@ func runPushSync(ctx context.Context, m *repo_model.PushMirror) error { if setting.LFS.StartServer { log.Trace("SyncMirrors [repo: %-v]: syncing LFS objects...", m.Repo) - gitRepo, err := git.OpenRepository(ctx, path) + gitRepo, err := repo_module.OpenRepository(ctx, repo) if err != nil { log.Error("OpenRepository: %v", err) return errors.New("Unexpected error") @@ -171,16 +176,15 @@ func runPushSync(ctx context.Context, m *repo_model.PushMirror) error { return nil } - err := performPush(m.Repo.RepoPath()) + err := performPush(m.Repo, false) if err != nil { return err } if m.Repo.HasWiki() { - wikiPath := m.Repo.WikiPath() - _, err := git.GetRemoteAddress(ctx, wikiPath, m.RemoteName) + _, err := git.GetRemoteAddress(ctx, m.Repo.WikiPath(), m.RemoteName) if err == nil { - err := performPush(wikiPath) + err := performPush(m.Repo, true) if err != nil { return err } diff --git a/services/pull/check.go b/services/pull/check.go index ebe4c6d61b038..39498e5c31faf 100644 --- a/services/pull/check.go +++ b/services/pull/check.go @@ -24,6 +24,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/queue" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/timeutil" asymkey_service "code.gitea.io/gitea/services/asymkey" notify_service "code.gitea.io/gitea/services/notify" @@ -215,7 +216,7 @@ func getMergeCommit(ctx context.Context, pr *issues_model.PullRequest) (*git.Com return nil, fmt.Errorf("GetFullCommitID(%s) in %s: %w", prHeadRef, pr.BaseRepo.FullName(), err) } - gitRepo, err := git.OpenRepository(ctx, pr.BaseRepo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(ctx, pr.BaseRepo) if err != nil { return nil, fmt.Errorf("%-v OpenRepository: %w", pr.BaseRepo, err) } diff --git a/services/pull/merge_rebase.go b/services/pull/merge_rebase.go index a88f805ef0252..6b2f0c4752233 100644 --- a/services/pull/merge_rebase.go +++ b/services/pull/merge_rebase.go @@ -10,6 +10,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" + repo_module "code.gitea.io/gitea/modules/repository" ) // getRebaseAmendMessage composes the message to amend commits in rebase merge of a pull request. @@ -57,7 +58,7 @@ func doMergeRebaseFastForward(ctx *mergeContext) error { } // Original repo to read template from. - baseGitRepo, err := git.OpenRepository(ctx, ctx.pr.BaseRepo.RepoPath()) + baseGitRepo, err := repo_module.OpenRepository(ctx, ctx.pr.BaseRepo) if err != nil { log.Error("Unable to get Git repo for rebase: %v", err) return err diff --git a/services/pull/pull.go b/services/pull/pull.go index 930954bdfdfa1..0791668b81b52 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -62,7 +62,7 @@ func NewPullRequest(ctx context.Context, repo *repo_model.Repository, issue *iss assigneeCommentMap := make(map[int64]*issues_model.Comment) // add first push codes comment - baseGitRepo, err := git.OpenRepository(ctx, pr.BaseRepo.RepoPath()) + baseGitRepo, err := repo_module.OpenRepository(ctx, pr.BaseRepo) if err != nil { return err } @@ -127,7 +127,7 @@ func NewPullRequest(ctx context.Context, repo *repo_model.Repository, issue *iss } if !pr.IsWorkInProgress(ctx) { - if err := issues_model.PullRequestCodeOwnersReview(ctx, issue, pr); err != nil { + if err := issue_service.PullRequestCodeOwnersReview(ctx, issue, pr); err != nil { return err } } @@ -269,7 +269,7 @@ func checkForInvalidation(ctx context.Context, requests issues_model.PullRequest if err != nil { return fmt.Errorf("GetRepositoryByIDCtx: %w", err) } - gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(ctx, repo) if err != nil { return fmt.Errorf("git.OpenRepository: %w", err) } @@ -845,7 +845,7 @@ func GetIssuesAllCommitStatus(ctx context.Context, issues issues_model.IssueList } gitRepo, ok := gitRepos[issue.RepoID] if !ok { - gitRepo, err = git.OpenRepository(ctx, issue.Repo.RepoPath()) + gitRepo, err = repo_module.OpenRepository(ctx, issue.Repo) if err != nil { log.Error("Cannot open git repository %-v for issue #%d[%d]. Error: %v", issue.Repo, issue.Index, issue.ID, err) continue diff --git a/services/pull/pull_test.go b/services/pull/pull_test.go index d63227a7d5e9c..4b9314e410099 100644 --- a/services/pull/pull_test.go +++ b/services/pull/pull_test.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/git" + repo_module "code.gitea.io/gitea/modules/repository" "github.com/stretchr/testify/assert" ) @@ -41,7 +42,7 @@ func TestPullRequest_GetDefaultMergeMessage_InternalTracker(t *testing.T) { pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) - gitRepo, err := git.OpenRepository(git.DefaultContext, pr.BaseRepo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(git.DefaultContext, pr.BaseRepo) assert.NoError(t, err) defer gitRepo.Close() @@ -71,7 +72,7 @@ func TestPullRequest_GetDefaultMergeMessage_ExternalTracker(t *testing.T) { pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2, BaseRepo: baseRepo}) assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) - gitRepo, err := git.OpenRepository(git.DefaultContext, pr.BaseRepo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(git.DefaultContext, pr.BaseRepo) assert.NoError(t, err) defer gitRepo.Close() diff --git a/services/release/release_test.go b/services/release/release_test.go index 4b57262981b55..b1bd0fad3d643 100644 --- a/services/release/release_test.go +++ b/services/release/release_test.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/services/attachment" _ "code.gitea.io/gitea/models/actions" @@ -29,9 +30,8 @@ func TestRelease_Create(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - repoPath := repo_model.RepoPath(user.Name, repo.Name) - gitRepo, err := git.OpenRepository(git.DefaultContext, repoPath) + gitRepo, err := repo_module.OpenRepository(git.DefaultContext, repo) assert.NoError(t, err) defer gitRepo.Close() @@ -135,9 +135,8 @@ func TestRelease_Update(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - repoPath := repo_model.RepoPath(user.Name, repo.Name) - gitRepo, err := git.OpenRepository(git.DefaultContext, repoPath) + gitRepo, err := repo_module.OpenRepository(git.DefaultContext, repo) assert.NoError(t, err) defer gitRepo.Close() @@ -278,9 +277,8 @@ func TestRelease_createTag(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - repoPath := repo_model.RepoPath(user.Name, repo.Name) - gitRepo, err := git.OpenRepository(git.DefaultContext, repoPath) + gitRepo, err := repo_module.OpenRepository(git.DefaultContext, repo) assert.NoError(t, err) defer gitRepo.Close() diff --git a/services/repository/adopt.go b/services/repository/adopt.go index 2e9b0c822f957..fcad2cc61730c 100644 --- a/services/repository/adopt.go +++ b/services/repository/adopt.go @@ -126,7 +126,7 @@ func adoptRepository(ctx context.Context, repoPath string, u *user_model.User, r repo.IsEmpty = false // Don't bother looking this repo in the context it won't be there - gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(ctx, repo) if err != nil { return fmt.Errorf("openRepository: %w", err) } diff --git a/services/repository/archiver/archiver.go b/services/repository/archiver/archiver.go index c2ad4d484a69e..0dce167609023 100644 --- a/services/repository/archiver/archiver.go +++ b/services/repository/archiver/archiver.go @@ -19,6 +19,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/queue" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/storage" ) @@ -209,7 +210,7 @@ func doArchive(ctx context.Context, r *ArchiveRequest) (*repo_model.RepoArchiver return nil, fmt.Errorf("archiver.LoadRepo failed: %w", err) } - gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(ctx, repo) if err != nil { return nil, err } diff --git a/services/repository/branch.go b/services/repository/branch.go index c1e6625ed4761..7d4e23e14291c 100644 --- a/services/repository/branch.go +++ b/services/repository/branch.go @@ -160,7 +160,7 @@ func loadOneBranch(ctx context.Context, repo *repo_model.Repository, dbBranch *g if pr.HasMerged { baseGitRepo, ok := repoIDToGitRepo[pr.BaseRepoID] if !ok { - baseGitRepo, err = git.OpenRepository(ctx, pr.BaseRepo.RepoPath()) + baseGitRepo, err = repo_module.OpenRepository(ctx, pr.BaseRepo) if err != nil { return nil, fmt.Errorf("OpenRepository: %v", err) } diff --git a/services/repository/create.go b/services/repository/create.go index 0e89573343e66..3f58518188705 100644 --- a/services/repository/create.go +++ b/services/repository/create.go @@ -175,7 +175,7 @@ func initRepository(ctx context.Context, repoPath string, u *user_model.User, re if len(opts.DefaultBranch) > 0 { repo.DefaultBranch = opts.DefaultBranch - gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(ctx, repo) if err != nil { return fmt.Errorf("openRepository: %w", err) } diff --git a/services/repository/files/content_test.go b/services/repository/files/content_test.go index 3ad3e3ab98b2a..1958b875a4710 100644 --- a/services/repository/files/content_test.go +++ b/services/repository/files/content_test.go @@ -6,11 +6,10 @@ package files import ( "testing" - repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/contexttest" - "code.gitea.io/gitea/modules/git" api "code.gitea.io/gitea/modules/structs" + repo_module "code.gitea.io/gitea/modules/repository" _ "code.gitea.io/gitea/models/actions" @@ -235,7 +234,7 @@ func TestGetBlobBySHA(t *testing.T) { ctx.SetParams(":id", "1") ctx.SetParams(":sha", sha) - gitRepo, err := git.OpenRepository(ctx, repo_model.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)) + gitRepo, err := repo_module.OpenRepository(ctx, ctx.Repo.Repository) if err != nil { t.Fail() } diff --git a/services/repository/files/file_test.go b/services/repository/files/file_test.go index 4e67ad1410856..a4d0dfa288409 100644 --- a/services/repository/files/file_test.go +++ b/services/repository/files/file_test.go @@ -8,7 +8,7 @@ import ( "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/contexttest" - "code.gitea.io/gitea/modules/git" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" @@ -109,7 +109,7 @@ func TestGetFileResponseFromCommit(t *testing.T) { repo := ctx.Repo.Repository branch := repo.DefaultBranch treePath := "README.md" - gitRepo, _ := git.OpenRepository(ctx, repo.RepoPath()) + gitRepo, _ := repo_module.OpenRepository(ctx, repo) defer gitRepo.Close() commit, _ := gitRepo.GetBranchCommit(branch) expectedFileResponse := getExpectedFileResponse() diff --git a/services/repository/fork.go b/services/repository/fork.go index a8ff2717b0688..37460c12105db 100644 --- a/services/repository/fork.go +++ b/services/repository/fork.go @@ -167,7 +167,7 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork return fmt.Errorf("createDelegateHooks: %w", err) } - gitRepo, err := git.OpenRepository(txCtx, repo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(txCtx, repo) if err != nil { return fmt.Errorf("OpenRepository: %w", err) } @@ -190,7 +190,7 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork log.Error("Copy language stat from oldRepo failed: %v", err) } - gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(ctx, repo) if err != nil { log.Error("Open created git repository failed: %v", err) } else { diff --git a/services/repository/hooks.go b/services/repository/hooks.go index 7b82f36b43fdd..774d932c93514 100644 --- a/services/repository/hooks.go +++ b/services/repository/hooks.go @@ -10,7 +10,6 @@ import ( "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/webhook" - "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" @@ -52,13 +51,13 @@ func SyncRepositoryHooks(ctx context.Context) error { // GenerateGitHooks generates git hooks from a template repository func GenerateGitHooks(ctx context.Context, templateRepo, generateRepo *repo_model.Repository) error { - generateGitRepo, err := git.OpenRepository(ctx, generateRepo.RepoPath()) + generateGitRepo, err := repo_module.OpenRepository(ctx, generateRepo) if err != nil { return err } defer generateGitRepo.Close() - templateGitRepo, err := git.OpenRepository(ctx, templateRepo.RepoPath()) + templateGitRepo, err := repo_module.OpenRepository(ctx, templateRepo) if err != nil { return err } diff --git a/services/repository/lfs.go b/services/repository/lfs.go index b437fda15d578..ee89c5dc2ce36 100644 --- a/services/repository/lfs.go +++ b/services/repository/lfs.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" ) @@ -69,7 +70,7 @@ func GarbageCollectLFSMetaObjectsForRepo(ctx context.Context, repo *repo_model.R } }() - gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(ctx, repo) if err != nil { log.Error("Unable to open git repository %-v: %v", repo, err) return err diff --git a/services/repository/push.go b/services/repository/push.go index e86eebde8110b..e8a01da426c40 100644 --- a/services/repository/push.go +++ b/services/repository/push.go @@ -86,17 +86,15 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error { return fmt.Errorf("GetRepositoryByOwnerAndName failed: %w", err) } - repoPath := repo.RepoPath() - - gitRepo, err := git.OpenRepository(ctx, repoPath) + gitRepo, err := repo_module.OpenRepository(ctx, repo) if err != nil { - return fmt.Errorf("OpenRepository[%s]: %w", repoPath, err) + return fmt.Errorf("OpenRepository[%s]: %w", repo.FullName(), err) } defer gitRepo.Close() objectFormat, err := gitRepo.GetObjectFormat() if err != nil { - return fmt.Errorf("unknown repository ObjectFormat [%s]: %w", repoPath, err) + return fmt.Errorf("unknown repository ObjectFormat [%s]: %w", repo.FullName(), err) } if err = repo_module.UpdateRepoSize(ctx, repo); err != nil { diff --git a/services/wiki/wiki_test.go b/services/wiki/wiki_test.go index 277fa086ac13c..8091303909e0b 100644 --- a/services/wiki/wiki_test.go +++ b/services/wiki/wiki_test.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + repo_module "code.gitea.io/gitea/modules/repository" _ "code.gitea.io/gitea/models/actions" @@ -164,7 +165,7 @@ func TestRepository_AddWikiPage(t *testing.T) { webPath := UserTitleToWebPath("", userTitle) assert.NoError(t, AddWikiPage(git.DefaultContext, doer, repo, webPath, wikiContent, commitMsg)) // Now need to show that the page has been added: - gitRepo, err := git.OpenRepository(git.DefaultContext, repo.WikiPath()) + gitRepo, err := repo_module.OpenWikiRepository(git.DefaultContext, repo) if !assert.NoError(t, err) { return } @@ -212,7 +213,7 @@ func TestRepository_EditWikiPage(t *testing.T) { assert.NoError(t, EditWikiPage(git.DefaultContext, doer, repo, "Home", webPath, newWikiContent, commitMsg)) // Now need to show that the page has been added: - gitRepo, err := git.OpenRepository(git.DefaultContext, repo.WikiPath()) + gitRepo, err := repo_module.OpenWikiRepository(git.DefaultContext, repo) assert.NoError(t, err) masterTree, err := gitRepo.GetTree(DefaultBranch) assert.NoError(t, err) @@ -236,7 +237,7 @@ func TestRepository_DeleteWikiPage(t *testing.T) { assert.NoError(t, DeleteWikiPage(git.DefaultContext, doer, repo, "Home")) // Now need to show that the page has been added: - gitRepo, err := git.OpenRepository(git.DefaultContext, repo.WikiPath()) + gitRepo, err := repo_module.OpenWikiRepository(git.DefaultContext, repo) if !assert.NoError(t, err) { return } @@ -251,7 +252,7 @@ func TestRepository_DeleteWikiPage(t *testing.T) { func TestPrepareWikiFileName(t *testing.T) { unittest.PrepareTestEnv(t) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - gitRepo, err := git.OpenRepository(git.DefaultContext, repo.WikiPath()) + gitRepo, err := repo_module.OpenWikiRepository(git.DefaultContext, repo) if !assert.NoError(t, err) { return } diff --git a/tests/integration/api_packages_cargo_test.go b/tests/integration/api_packages_cargo_test.go index 6b8154af457a6..0e3204fbf059a 100644 --- a/tests/integration/api_packages_cargo_test.go +++ b/tests/integration/api_packages_cargo_test.go @@ -18,9 +18,9 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/json" cargo_module "code.gitea.io/gitea/modules/packages/cargo" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" cargo_router "code.gitea.io/gitea/routers/api/packages/cargo" cargo_service "code.gitea.io/gitea/services/packages/cargo" @@ -78,7 +78,7 @@ func testPackageCargo(t *testing.T, _ *neturl.URL) { assert.NoError(t, err) readGitContent := func(t *testing.T, path string) string { - gitRepo, err := git.OpenRepository(db.DefaultContext, repo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(db.DefaultContext, repo) assert.NoError(t, err) defer gitRepo.Close() diff --git a/tests/integration/api_releases_test.go b/tests/integration/api_releases_test.go index e070bd05b5a42..1bfdd529f0bdd 100644 --- a/tests/integration/api_releases_test.go +++ b/tests/integration/api_releases_test.go @@ -18,6 +18,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + repo_module "code.gitea.io/gitea/modules/repository" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/tests" @@ -109,7 +110,7 @@ func TestAPICreateAndUpdateRelease(t *testing.T) { session := loginUser(t, owner.LowerName) token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) - gitRepo, err := git.OpenRepository(git.DefaultContext, repo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(git.DefaultContext, repo) assert.NoError(t, err) defer gitRepo.Close() @@ -172,7 +173,7 @@ func TestAPICreateReleaseToDefaultBranchOnExistingTag(t *testing.T) { session := loginUser(t, owner.LowerName) token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) - gitRepo, err := git.OpenRepository(git.DefaultContext, repo.RepoPath()) + gitRepo, err := repo_module.OpenRepository(git.DefaultContext, repo) assert.NoError(t, err) defer gitRepo.Close() diff --git a/tests/integration/api_repo_file_create_test.go b/tests/integration/api_repo_file_create_test.go index f78909eb32582..ace7452f1006f 100644 --- a/tests/integration/api_repo_file_create_test.go +++ b/tests/integration/api_repo_file_create_test.go @@ -18,7 +18,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/git" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" @@ -167,7 +167,7 @@ func TestAPICreateFile(t *testing.T) { req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user2.Name, repo1.Name, treePath), &createFileOptions). AddTokenAuth(token2) resp := MakeRequest(t, req, http.StatusCreated) - gitRepo, _ := git.OpenRepository(stdCtx.Background(), repo1.RepoPath()) + gitRepo, _ := repo_module.OpenRepository(stdCtx.Background(), repo1) commitID, _ := gitRepo.GetBranchCommitID(createFileOptions.NewBranchName) latestCommit, _ := gitRepo.GetCommitByPath(treePath) expectedFileResponse := getExpectedFileResponseForCreate("user2/repo1", commitID, treePath, latestCommit.ID.String()) @@ -285,7 +285,7 @@ func TestAPICreateFile(t *testing.T) { AddTokenAuth(token2) resp = MakeRequest(t, req, http.StatusCreated) emptyRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user2", Name: "empty-repo"}) // public repo - gitRepo, _ := git.OpenRepository(stdCtx.Background(), emptyRepo.RepoPath()) + gitRepo, _ := repo_module.OpenRepository(stdCtx.Background(), emptyRepo) commitID, _ := gitRepo.GetBranchCommitID(createFileOptions.NewBranchName) latestCommit, _ := gitRepo.GetCommitByPath(treePath) expectedFileResponse := getExpectedFileResponseForCreate("user2/empty-repo", commitID, treePath, latestCommit.ID.String()) diff --git a/tests/integration/api_repo_file_update_test.go b/tests/integration/api_repo_file_update_test.go index 7e88f6cd80360..28af8370cd56d 100644 --- a/tests/integration/api_repo_file_update_test.go +++ b/tests/integration/api_repo_file_update_test.go @@ -17,7 +17,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/git" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" @@ -135,7 +135,7 @@ func TestAPIUpdateFile(t *testing.T) { req := NewRequestWithJSON(t, "PUT", fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user2.Name, repo1.Name, treePath), &updateFileOptions). AddTokenAuth(token2) resp := MakeRequest(t, req, http.StatusOK) - gitRepo, _ := git.OpenRepository(stdCtx.Background(), repo1.RepoPath()) + gitRepo, _ := repo_module.OpenRepository(stdCtx.Background(), repo1) commitID, _ := gitRepo.GetBranchCommitID(updateFileOptions.NewBranchName) lasCommit, _ := gitRepo.GetCommitByPath(treePath) expectedFileResponse := getExpectedFileResponseForUpdate(commitID, treePath, lasCommit.ID.String()) diff --git a/tests/integration/api_repo_files_change_test.go b/tests/integration/api_repo_files_change_test.go index d500d48b36091..b829512d0425c 100644 --- a/tests/integration/api_repo_files_change_test.go +++ b/tests/integration/api_repo_files_change_test.go @@ -16,7 +16,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/git" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" @@ -96,7 +96,7 @@ func TestAPIChangeFiles(t *testing.T) { req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/contents", user2.Name, repo1.Name), &changeFilesOptions). AddTokenAuth(token2) resp := MakeRequest(t, req, http.StatusCreated) - gitRepo, _ := git.OpenRepository(stdCtx.Background(), repo1.RepoPath()) + gitRepo, _ := repo_module.OpenRepository(stdCtx.Background(), repo1) commitID, _ := gitRepo.GetBranchCommitID(changeFilesOptions.NewBranchName) createLasCommit, _ := gitRepo.GetCommitByPath(createTreePath) updateLastCommit, _ := gitRepo.GetCommitByPath(updateTreePath) diff --git a/tests/integration/api_repo_get_contents_list_test.go b/tests/integration/api_repo_get_contents_list_test.go index 86313f5e3b209..8c9dfca38be83 100644 --- a/tests/integration/api_repo_get_contents_list_test.go +++ b/tests/integration/api_repo_get_contents_list_test.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" repo_service "code.gitea.io/gitea/services/repository" @@ -71,7 +72,7 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) { token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository) // Get the commit ID of the default branch - gitRepo, err := git.OpenRepository(git.DefaultContext, repo1.RepoPath()) + gitRepo, err := repo_module.OpenRepository(git.DefaultContext, repo1) assert.NoError(t, err) defer gitRepo.Close() diff --git a/tests/integration/api_repo_get_contents_test.go b/tests/integration/api_repo_get_contents_test.go index ffbdfcb0fab81..6f6c65c226298 100644 --- a/tests/integration/api_repo_get_contents_test.go +++ b/tests/integration/api_repo_get_contents_test.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" repo_service "code.gitea.io/gitea/services/repository" @@ -73,7 +74,7 @@ func testAPIGetContents(t *testing.T, u *url.URL) { token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository) // Get the commit ID of the default branch - gitRepo, err := git.OpenRepository(git.DefaultContext, repo1.RepoPath()) + gitRepo, err := repo_module.OpenRepository(git.DefaultContext, repo1) assert.NoError(t, err) defer gitRepo.Close() diff --git a/tests/integration/api_repo_git_tags_test.go b/tests/integration/api_repo_git_tags_test.go index 2e8510ab1b3ae..17ab27bc73c5f 100644 --- a/tests/integration/api_repo_git_tags_test.go +++ b/tests/integration/api_repo_git_tags_test.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + repo_module "code.gitea.io/gitea/modules/repository" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/tests" @@ -32,7 +33,7 @@ func TestAPIGitTags(t *testing.T) { _ = git.NewCommand(git.DefaultContext, "config", "user.name").AddDynamicArguments(user.Name).Run(&git.RunOpts{Dir: repo.RepoPath()}) _ = git.NewCommand(git.DefaultContext, "config", "user.email").AddDynamicArguments(user.Email).Run(&git.RunOpts{Dir: repo.RepoPath()}) - gitRepo, _ := git.OpenRepository(git.DefaultContext, repo.RepoPath()) + gitRepo, _ := repo_module.OpenRepository(git.DefaultContext, repo) defer gitRepo.Close() commit, _ := gitRepo.GetBranchCommit("master") diff --git a/tests/integration/mirror_pull_test.go b/tests/integration/mirror_pull_test.go index 1e0edd9a2dd07..fd5946f345005 100644 --- a/tests/integration/mirror_pull_test.go +++ b/tests/integration/mirror_pull_test.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/migration" "code.gitea.io/gitea/modules/repository" + repo_module "code.gitea.io/gitea/modules/repository" mirror_service "code.gitea.io/gitea/services/mirror" release_service "code.gitea.io/gitea/services/release" repo_service "code.gitea.io/gitea/services/repository" @@ -54,7 +55,7 @@ func TestMirrorPull(t *testing.T) { mirror, err := repository.MigrateRepositoryGitData(ctx, user, mirrorRepo, opts, nil) assert.NoError(t, err) - gitRepo, err := git.OpenRepository(git.DefaultContext, repoPath) + gitRepo, err := repo_module.OpenRepository(git.DefaultContext, repo) assert.NoError(t, err) defer gitRepo.Close() diff --git a/tests/integration/mirror_push_test.go b/tests/integration/mirror_push_test.go index c6f0c856163bd..aa775d17e2f41 100644 --- a/tests/integration/mirror_push_test.go +++ b/tests/integration/mirror_push_test.go @@ -17,6 +17,7 @@ import ( user_model "code.gitea.io/gitea/models/user" gitea_context "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/services/migrations" mirror_service "code.gitea.io/gitea/services/mirror" @@ -55,14 +56,14 @@ func testMirrorPush(t *testing.T, u *url.URL) { ok := mirror_service.SyncPushMirror(context.Background(), mirrors[0].ID) assert.True(t, ok) - srcGitRepo, err := git.OpenRepository(git.DefaultContext, srcRepo.RepoPath()) + srcGitRepo, err := repo_module.OpenRepository(git.DefaultContext, srcRepo) assert.NoError(t, err) defer srcGitRepo.Close() srcCommit, err := srcGitRepo.GetBranchCommit("master") assert.NoError(t, err) - mirrorGitRepo, err := git.OpenRepository(git.DefaultContext, mirrorRepo.RepoPath()) + mirrorGitRepo, err := repo_module.OpenRepository(git.DefaultContext, mirrorRepo) assert.NoError(t, err) defer mirrorGitRepo.Close() diff --git a/tests/integration/repofiles_change_test.go b/tests/integration/repofiles_change_test.go index e0edf07299b50..c4575d984f2ab 100644 --- a/tests/integration/repofiles_change_test.go +++ b/tests/integration/repofiles_change_test.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/contexttest" "code.gitea.io/gitea/modules/git" + repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" files_service "code.gitea.io/gitea/services/repository/files" @@ -262,7 +263,7 @@ func TestChangeRepoFilesForCreate(t *testing.T) { // asserts assert.NoError(t, err) - gitRepo, _ := git.OpenRepository(git.DefaultContext, repo.RepoPath()) + gitRepo, _ := repo_module.OpenRepository(git.DefaultContext, repo) defer gitRepo.Close() commitID, _ := gitRepo.GetBranchCommitID(opts.NewBranch) @@ -299,7 +300,7 @@ func TestChangeRepoFilesForUpdate(t *testing.T) { // asserts assert.NoError(t, err) - gitRepo, _ := git.OpenRepository(git.DefaultContext, repo.RepoPath()) + gitRepo, _ := repo_module.OpenRepository(git.DefaultContext, repo) defer gitRepo.Close() commit, _ := gitRepo.GetBranchCommit(opts.NewBranch) @@ -335,7 +336,7 @@ func TestChangeRepoFilesForUpdateWithFileMove(t *testing.T) { // asserts assert.NoError(t, err) - gitRepo, _ := git.OpenRepository(git.DefaultContext, repo.RepoPath()) + gitRepo, _ := repo_module.OpenRepository(git.DefaultContext, repo) defer gitRepo.Close() commit, _ := gitRepo.GetBranchCommit(opts.NewBranch) @@ -386,7 +387,7 @@ func TestChangeRepoFilesWithoutBranchNames(t *testing.T) { // asserts assert.NoError(t, err) - gitRepo, _ := git.OpenRepository(git.DefaultContext, repo.RepoPath()) + gitRepo, _ := repo_module.OpenRepository(git.DefaultContext, repo) defer gitRepo.Close() commit, _ := gitRepo.GetBranchCommit(repo.DefaultBranch) From a5c19b19d54bba9c80e8d2411e5430c3725b0090 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 26 Jan 2024 13:02:00 +0800 Subject: [PATCH 02/18] Use a standalone package --- cmd/admin.go | 3 +- modules/context/api.go | 4 +- modules/context/repo.go | 5 +- modules/contexttest/context_tests.go | 6 +- modules/gitrepo/gitrepo.go | 32 + modules/indexer/stats/db.go | 4 +- modules/repository/branch.go | 3 +- modules/repository/generate.go | 3 +- modules/repository/migrate.go | 363 ------------ modules/repository/repo.go | 546 +++++++++++++++++- modules/repository/tag.go | 194 ------- modules/repository/wiki.go | 36 -- routers/api/v1/repo/branch.go | 5 +- routers/api/v1/repo/file.go | 4 +- routers/api/v1/repo/pull.go | 6 +- routers/api/v1/repo/repo.go | 3 +- routers/api/v1/repo/wiki.go | 4 +- routers/private/internal_repo.go | 4 +- routers/web/repo/commit.go | 6 +- routers/web/repo/compare.go | 8 +- routers/web/repo/editor_test.go | 4 +- routers/web/repo/pull.go | 12 +- routers/web/repo/wiki.go | 4 +- routers/web/repo/wiki_test.go | 4 +- routers/web/shared/user/header.go | 4 +- services/actions/notifier_helper.go | 4 +- services/automerge/automerge.go | 8 +- services/convert/pull.go | 10 +- services/doctor/misc.go | 4 +- services/issue/issue.go | 4 +- services/migrations/gitea_uploader.go | 3 +- services/migrations/gitea_uploader_test.go | 6 +- services/mirror/mirror_pull.go | 5 +- services/mirror/mirror_push.go | 4 +- services/pull/check.go | 4 +- services/pull/merge_rebase.go | 4 +- services/pull/pull.go | 7 +- services/pull/pull_test.go | 6 +- services/release/release_test.go | 8 +- services/repository/adopt.go | 3 +- services/repository/archiver/archiver.go | 4 +- services/repository/branch.go | 3 +- services/repository/create.go | 3 +- services/repository/files/content_test.go | 4 +- services/repository/files/file_test.go | 4 +- services/repository/fork.go | 5 +- services/repository/hooks.go | 5 +- services/repository/lfs.go | 4 +- services/repository/push.go | 3 +- services/wiki/wiki_test.go | 10 +- tests/integration/api_packages_cargo_test.go | 4 +- tests/integration/api_releases_test.go | 6 +- .../integration/api_repo_file_create_test.go | 6 +- .../integration/api_repo_file_update_test.go | 4 +- .../integration/api_repo_files_change_test.go | 4 +- .../api_repo_get_contents_list_test.go | 4 +- .../integration/api_repo_get_contents_test.go | 4 +- tests/integration/api_repo_git_tags_test.go | 4 +- tests/integration/mirror_pull_test.go | 4 +- tests/integration/mirror_push_test.go | 6 +- tests/integration/repofiles_change_test.go | 10 +- 61 files changed, 716 insertions(+), 732 deletions(-) create mode 100644 modules/gitrepo/gitrepo.go delete mode 100644 modules/repository/migrate.go delete mode 100644 modules/repository/tag.go delete mode 100644 modules/repository/wiki.go diff --git a/cmd/admin.go b/cmd/admin.go index 02f6db07fcd6f..6c9480e76eb7a 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -11,6 +11,7 @@ import ( "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" @@ -122,7 +123,7 @@ func runRepoSyncReleases(_ *cli.Context) error { log.Trace("Processing next %d repos of %d", len(repos), count) for _, repo := range repos { log.Trace("Synchronizing repo %s with path %s", repo.FullName(), repo.RepoPath()) - gitRepo, err := repo_module.OpenRepository(ctx, repo) + gitRepo, err := gitrepo.OpenRepository(ctx, repo) if err != nil { log.Warn("OpenRepository: %v", err) continue diff --git a/modules/context/api.go b/modules/context/api.go index cd495c41e8ca0..3ac70d4857d79 100644 --- a/modules/context/api.go +++ b/modules/context/api.go @@ -15,9 +15,9 @@ import ( user_model "code.gitea.io/gitea/models/user" mc "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/httpcache" "code.gitea.io/gitea/modules/log" - repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/web" web_types "code.gitea.io/gitea/modules/web/types" @@ -278,7 +278,7 @@ func ReferencesGitRepo(allowEmpty ...bool) func(ctx *APIContext) (cancel context // For API calls. if ctx.Repo.GitRepo == nil { - gitRepo, err := repo_module.OpenRepository(ctx, ctx.Repo.Repository) + gitRepo, err := gitrepo.OpenRepository(ctx, ctx.Repo.Repository) if err != nil { ctx.Error(http.StatusInternalServerError, fmt.Sprintf("Open Repository %v failed", ctx.Repo.Repository.FullName()), err) return cancel diff --git a/modules/context/repo.go b/modules/context/repo.go index 46d41a700fe9b..75ebfec705447 100644 --- a/modules/context/repo.go +++ b/modules/context/repo.go @@ -23,6 +23,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" code_indexer "code.gitea.io/gitea/modules/indexer/code" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" @@ -633,7 +634,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc { return nil } - gitRepo, err := repo_module.OpenRepository(ctx, repo) + gitRepo, err := gitrepo.OpenRepository(ctx, repo) if err != nil { if strings.Contains(err.Error(), "repository does not exist") || strings.Contains(err.Error(), "no such file or directory") { log.Error("Repository %-v has a broken repository on the file system: %s Error: %v", ctx.Repo.Repository, ctx.Repo.Repository.RepoPath(), err) @@ -920,7 +921,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context ) if ctx.Repo.GitRepo == nil { - ctx.Repo.GitRepo, err = repo_module.OpenRepository(ctx, ctx.Repo.Repository) + ctx.Repo.GitRepo, err = gitrepo.OpenRepository(ctx, ctx.Repo.Repository) if err != nil { ctx.ServerError(fmt.Sprintf("Open Repository %v failed", ctx.Repo.Repository.FullName()), err) return nil diff --git a/modules/contexttest/context_tests.go b/modules/contexttest/context_tests.go index 9dafabb30dd2b..9ca028bb6ec26 100644 --- a/modules/contexttest/context_tests.go +++ b/modules/contexttest/context_tests.go @@ -18,7 +18,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/templates" "code.gitea.io/gitea/modules/translation" "code.gitea.io/gitea/modules/web/middleware" @@ -107,7 +107,7 @@ func LoadRepoCommit(t *testing.T, ctx gocontext.Context) { assert.FailNow(t, "context is not *context.Context or *context.APIContext") } - gitRepo, err := repo_module.OpenRepository(ctx, repo.Repository) + gitRepo, err := gitrepo.OpenRepository(ctx, repo.Repository) assert.NoError(t, err) defer gitRepo.Close() branch, err := gitRepo.GetHEADBranch() @@ -137,7 +137,7 @@ func LoadUser(t *testing.T, ctx gocontext.Context, userID int64) { func LoadGitRepo(t *testing.T, ctx *context.Context) { assert.NoError(t, ctx.Repo.Repository.LoadOwner(ctx)) var err error - ctx.Repo.GitRepo, err = repo_module.OpenRepository(ctx, ctx.Repo.Repository) + ctx.Repo.GitRepo, err = gitrepo.OpenRepository(ctx, ctx.Repo.Repository) assert.NoError(t, err) } diff --git a/modules/gitrepo/gitrepo.go b/modules/gitrepo/gitrepo.go new file mode 100644 index 0000000000000..2af4cda60d9bf --- /dev/null +++ b/modules/gitrepo/gitrepo.go @@ -0,0 +1,32 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package gitrepo + +import ( + "context" + "fmt" + + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/util" +) + +type Repository = git.Repository + +// OpenRepository opens the repository at the given relative path with the provided context. +func OpenRepository(ctx context.Context, repoPath *repo_model.Repository) (*Repository, error) { + return git.OpenRepository(ctx, repoPath.RepoPath()) +} + +func OpenWikiRepository(ctx context.Context, repoPath *repo_model.Repository) (*Repository, error) { + return git.OpenRepository(ctx, repoPath.WikiPath()) +} + +// DeleteRepository deletes the repository at the given relative path with the provided context. +func DeleteRepository(ctx context.Context, repo *repo_model.Repository) error { + if err := util.RemoveAll(repo.RepoPath()); err != nil { + return fmt.Errorf("failed to remove %s: %w", repo.FullName(), err) + } + return nil +} diff --git a/modules/indexer/stats/db.go b/modules/indexer/stats/db.go index 9842e6470be6a..98a977c7008fe 100644 --- a/modules/indexer/stats/db.go +++ b/modules/indexer/stats/db.go @@ -8,10 +8,10 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" - repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" ) @@ -36,7 +36,7 @@ func (db *DBIndexer) Index(id int64) error { return err } - gitRepo, err := repo_module.OpenRepository(ctx, repo) + gitRepo, err := gitrepo.OpenRepository(ctx, repo) if err != nil { if err.Error() == "no such file or directory" { return nil diff --git a/modules/repository/branch.go b/modules/repository/branch.go index c82bc719cee75..e448490f4ac18 100644 --- a/modules/repository/branch.go +++ b/modules/repository/branch.go @@ -11,6 +11,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/timeutil" ) @@ -24,7 +25,7 @@ func SyncRepoBranches(ctx context.Context, repoID, doerID int64) (int64, error) log.Debug("SyncRepoBranches: in Repo[%d:%s]", repo.ID, repo.FullName()) - gitRepo, err := OpenRepository(ctx, repo) + gitRepo, err := gitrepo.OpenRepository(ctx, repo) if err != nil { log.Error("OpenRepository[%s]: %w", repo.FullName(), err) return 0, err diff --git a/modules/repository/generate.go b/modules/repository/generate.go index da2f2987511bc..b32c4e058e503 100644 --- a/modules/repository/generate.go +++ b/modules/repository/generate.go @@ -19,6 +19,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/util" @@ -271,7 +272,7 @@ func generateGitContent(ctx context.Context, repo, templateRepo, generateRepo *r repo.DefaultBranch = templateRepo.DefaultBranch } - gitRepo, err := OpenRepository(ctx, repo) + gitRepo, err := gitrepo.OpenRepository(ctx, repo) if err != nil { return fmt.Errorf("openRepository: %w", err) } diff --git a/modules/repository/migrate.go b/modules/repository/migrate.go deleted file mode 100644 index 7331738c3bdd0..0000000000000 --- a/modules/repository/migrate.go +++ /dev/null @@ -1,363 +0,0 @@ -// Copyright 2024 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package repository - -import ( - "context" - "errors" - "fmt" - "io" - "net/http" - "strings" - "time" - - "code.gitea.io/gitea/models/db" - git_model "code.gitea.io/gitea/models/git" - "code.gitea.io/gitea/models/organization" - repo_model "code.gitea.io/gitea/models/repo" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/lfs" - "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/migration" - "code.gitea.io/gitea/modules/setting" - "code.gitea.io/gitea/modules/timeutil" - "code.gitea.io/gitea/modules/util" -) - -// MigrateRepositoryGitData starts migrating git related data after created migrating repository -func MigrateRepositoryGitData(ctx context.Context, u *user_model.User, - repo *repo_model.Repository, opts migration.MigrateOptions, - httpTransport *http.Transport, -) (*repo_model.Repository, error) { - repoPath := repo_model.RepoPath(u.Name, opts.RepoName) - - if u.IsOrganization() { - t, err := organization.OrgFromUser(u).GetOwnerTeam(ctx) - 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 = util.RemoveAll(repoPath); err != nil { - return repo, fmt.Errorf("Failed to remove %s: %w", repoPath, err) - } - - if err = git.Clone(ctx, opts.CloneAddr, repoPath, git.CloneRepoOptions{ - Mirror: true, - Quiet: true, - Timeout: migrateTimeout, - SkipTLSVerify: setting.Migrations.SkipTLSVerify, - }); err != nil { - if errors.Is(err, context.DeadlineExceeded) { - return repo, fmt.Errorf("Clone timed out. Consider increasing [git.timeout] MIGRATE in app.ini. Underlying Error: %w", err) - } - return repo, fmt.Errorf("Clone: %w", err) - } - - if err := git.WriteCommitGraph(ctx, repoPath); err != nil { - return repo, err - } - - if opts.Wiki { - wikiPath := repo_model.WikiPath(u.Name, opts.RepoName) - wikiRemotePath := WikiRemoteURL(ctx, opts.CloneAddr) - if len(wikiRemotePath) > 0 { - if err := util.RemoveAll(wikiPath); err != nil { - return repo, fmt.Errorf("Failed to remove %s: %w", wikiPath, err) - } - - if err := git.Clone(ctx, wikiRemotePath, wikiPath, git.CloneRepoOptions{ - Mirror: true, - Quiet: true, - Timeout: migrateTimeout, - Branch: "master", - SkipTLSVerify: setting.Migrations.SkipTLSVerify, - }); err != nil { - log.Warn("Clone wiki: %v", err) - if err := util.RemoveAll(wikiPath); err != nil { - return repo, fmt.Errorf("Failed to remove %s: %w", wikiPath, err) - } - } else { - if err := git.WriteCommitGraph(ctx, wikiPath); err != nil { - return repo, err - } - } - } - } - - if repo.OwnerID == u.ID { - repo.Owner = u - } - - if err = CheckDaemonExportOK(ctx, repo); err != nil { - return repo, fmt.Errorf("checkDaemonExportOK: %w", err) - } - - if stdout, _, err := git.NewCommand(ctx, "update-server-info"). - SetDescription(fmt.Sprintf("MigrateRepositoryGitData(git update-server-info): %s", repoPath)). - RunStdString(&git.RunOpts{Dir: repoPath}); err != nil { - log.Error("MigrateRepositoryGitData(git update-server-info) in %v: Stdout: %s\nError: %v", repo, stdout, err) - return repo, fmt.Errorf("error in MigrateRepositoryGitData(git update-server-info): %w", err) - } - - gitRepo, err := git.OpenRepository(ctx, repoPath) - if err != nil { - return repo, fmt.Errorf("OpenRepository: %w", err) - } - defer gitRepo.Close() - - repo.IsEmpty, err = gitRepo.IsEmpty() - if err != nil { - return repo, fmt.Errorf("git.IsEmpty: %w", err) - } - - if !repo.IsEmpty { - if len(repo.DefaultBranch) == 0 { - // Try to get HEAD branch and set it as default branch. - headBranch, err := gitRepo.GetHEADBranch() - if err != nil { - return repo, fmt.Errorf("GetHEADBranch: %w", err) - } - if headBranch != nil { - repo.DefaultBranch = headBranch.Name - } - } - - if _, err := SyncRepoBranchesWithRepo(ctx, repo, gitRepo, u.ID); err != nil { - return repo, fmt.Errorf("SyncRepoBranchesWithRepo: %v", err) - } - - if !opts.Releases { - // note: this will greatly improve release (tag) sync - // for pull-mirrors with many tags - repo.IsMirror = opts.Mirror - if err = SyncReleasesWithTags(ctx, repo, gitRepo); err != nil { - log.Error("Failed to synchronize tags to releases for repository: %v", err) - } - } - - if opts.LFS { - endpoint := lfs.DetermineEndpoint(opts.CloneAddr, opts.LFSEndpoint) - lfsClient := lfs.NewClient(endpoint, httpTransport) - if err = StoreMissingLfsObjectsInRepository(ctx, repo, gitRepo, lfsClient); err != nil { - log.Error("Failed to store missing LFS objects for repository: %v", err) - } - } - } - - ctx, committer, err := db.TxContext(ctx) - if err != nil { - return nil, err - } - defer committer.Close() - - if opts.Mirror { - remoteAddress, err := util.SanitizeURL(opts.CloneAddr) - if err != nil { - return repo, err - } - mirrorModel := repo_model.Mirror{ - RepoID: repo.ID, - Interval: setting.Mirror.DefaultInterval, - EnablePrune: true, - NextUpdateUnix: timeutil.TimeStampNow().AddDuration(setting.Mirror.DefaultInterval), - LFS: opts.LFS, - RemoteAddress: remoteAddress, - } - if opts.LFS { - mirrorModel.LFSEndpoint = opts.LFSEndpoint - } - - if opts.MirrorInterval != "" { - parsedInterval, err := time.ParseDuration(opts.MirrorInterval) - if err != nil { - log.Error("Failed to set Interval: %v", err) - return repo, err - } - if parsedInterval == 0 { - mirrorModel.Interval = 0 - mirrorModel.NextUpdateUnix = 0 - } else if parsedInterval < setting.Mirror.MinInterval { - err := fmt.Errorf("interval %s is set below Minimum Interval of %s", parsedInterval, setting.Mirror.MinInterval) - log.Error("Interval: %s is too frequent", opts.MirrorInterval) - return repo, err - } else { - mirrorModel.Interval = parsedInterval - mirrorModel.NextUpdateUnix = timeutil.TimeStampNow().AddDuration(parsedInterval) - } - } - - if err = repo_model.InsertMirror(ctx, &mirrorModel); err != nil { - return repo, fmt.Errorf("InsertOne: %w", err) - } - - repo.IsMirror = true - if err = UpdateRepository(ctx, repo, false); err != nil { - return nil, err - } - - // this is necessary for sync local tags from remote - configName := fmt.Sprintf("remote.%s.fetch", mirrorModel.GetRemoteName()) - if stdout, _, err := git.NewCommand(ctx, "config"). - AddOptionValues("--add", configName, `+refs/tags/*:refs/tags/*`). - RunStdString(&git.RunOpts{Dir: repoPath}); err != nil { - log.Error("MigrateRepositoryGitData(git config --add +refs/tags/*:refs/tags/*) in %v: Stdout: %s\nError: %v", repo, stdout, err) - return repo, fmt.Errorf("error in MigrateRepositoryGitData(git config --add +refs/tags/*:refs/tags/*): %w", err) - } - } else { - if err = UpdateRepoSize(ctx, repo); err != nil { - log.Error("Failed to update size for repository: %v", err) - } - if repo, err = CleanUpMigrateInfo(ctx, repo); err != nil { - return nil, err - } - } - - return repo, committer.Commit() -} - -// cleanUpMigrateGitConfig removes mirror info which prevents "push --all". -// This also removes possible user credentials. -func cleanUpMigrateGitConfig(ctx context.Context, repoPath string) error { - cmd := git.NewCommand(ctx, "remote", "rm", "origin") - // if the origin does not exist - _, stderr, err := cmd.RunStdString(&git.RunOpts{ - Dir: repoPath, - }) - if err != nil && !strings.HasPrefix(stderr, "fatal: No such remote") { - return err - } - return nil -} - -// CleanUpMigrateInfo finishes migrating repository and/or wiki with things that don't need to be done for mirrors. -func CleanUpMigrateInfo(ctx context.Context, repo *repo_model.Repository) (*repo_model.Repository, error) { - repoPath := repo.RepoPath() - if err := CreateDelegateHooks(repoPath); err != nil { - return repo, fmt.Errorf("createDelegateHooks: %w", err) - } - if repo.HasWiki() { - if err := CreateDelegateHooks(repo.WikiPath()); err != nil { - return repo, fmt.Errorf("createDelegateHooks.(wiki): %w", err) - } - } - - _, _, err := git.NewCommand(ctx, "remote", "rm", "origin").RunStdString(&git.RunOpts{Dir: repoPath}) - if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") { - return repo, fmt.Errorf("CleanUpMigrateInfo: %w", err) - } - - if repo.HasWiki() { - if err := cleanUpMigrateGitConfig(ctx, repo.WikiPath()); err != nil { - return repo, fmt.Errorf("cleanUpMigrateGitConfig (wiki): %w", err) - } - } - - return repo, UpdateRepository(ctx, repo, false) -} - -// StoreMissingLfsObjectsInRepository downloads missing LFS objects -func StoreMissingLfsObjectsInRepository(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, lfsClient lfs.Client) error { - contentStore := lfs.NewContentStore() - - pointerChan := make(chan lfs.PointerBlob) - errChan := make(chan error, 1) - go lfs.SearchPointerBlobs(ctx, gitRepo, pointerChan, errChan) - - downloadObjects := func(pointers []lfs.Pointer) error { - err := lfsClient.Download(ctx, pointers, func(p lfs.Pointer, content io.ReadCloser, objectError error) error { - if objectError != nil { - return objectError - } - - defer content.Close() - - _, err := git_model.NewLFSMetaObject(ctx, repo.ID, p) - if err != nil { - log.Error("Repo[%-v]: Error creating LFS meta object %-v: %v", repo, p, err) - return err - } - - if err := contentStore.Put(p, content); err != nil { - log.Error("Repo[%-v]: Error storing content for LFS meta object %-v: %v", repo, p, err) - if _, err2 := git_model.RemoveLFSMetaObjectByOid(ctx, repo.ID, p.Oid); err2 != nil { - log.Error("Repo[%-v]: Error removing LFS meta object %-v: %v", repo, p, err2) - } - return err - } - return nil - }) - if err != nil { - select { - case <-ctx.Done(): - return nil - default: - } - } - return err - } - - var batch []lfs.Pointer - for pointerBlob := range pointerChan { - meta, err := git_model.GetLFSMetaObjectByOid(ctx, repo.ID, pointerBlob.Oid) - if err != nil && err != git_model.ErrLFSObjectNotExist { - log.Error("Repo[%-v]: Error querying LFS meta object %-v: %v", repo, pointerBlob.Pointer, err) - return err - } - if meta != nil { - log.Trace("Repo[%-v]: Skipping unknown LFS meta object %-v", repo, pointerBlob.Pointer) - continue - } - - log.Trace("Repo[%-v]: LFS object %-v not present in repository", repo, pointerBlob.Pointer) - - exist, err := contentStore.Exists(pointerBlob.Pointer) - if err != nil { - log.Error("Repo[%-v]: Error checking if LFS object %-v exists: %v", repo, pointerBlob.Pointer, err) - return err - } - - if exist { - log.Trace("Repo[%-v]: LFS object %-v already present; creating meta object", repo, pointerBlob.Pointer) - _, err := git_model.NewLFSMetaObject(ctx, repo.ID, pointerBlob.Pointer) - if err != nil { - log.Error("Repo[%-v]: Error creating LFS meta object %-v: %v", repo, pointerBlob.Pointer, err) - return err - } - } else { - if setting.LFS.MaxFileSize > 0 && pointerBlob.Size > setting.LFS.MaxFileSize { - log.Info("Repo[%-v]: LFS object %-v download denied because of LFS_MAX_FILE_SIZE=%d < size %d", repo, pointerBlob.Pointer, setting.LFS.MaxFileSize, pointerBlob.Size) - continue - } - - batch = append(batch, pointerBlob.Pointer) - if len(batch) >= lfsClient.BatchSize() { - if err := downloadObjects(batch); err != nil { - return err - } - batch = nil - } - } - } - if len(batch) > 0 { - if err := downloadObjects(batch); err != nil { - return err - } - } - - err, has := <-errChan - if has { - log.Error("Repo[%-v]: Error enumerating LFS objects for repository: %v", repo, err) - return err - } - - return nil -} diff --git a/modules/repository/repo.go b/modules/repository/repo.go index 9e38af1246c3a..5af69763d152e 100644 --- a/modules/repository/repo.go +++ b/modules/repository/repo.go @@ -5,24 +5,554 @@ package repository import ( "context" + "errors" "fmt" + "io" + "net/http" + "strings" + "time" + "code.gitea.io/gitea/models/db" + git_model "code.gitea.io/gitea/models/git" + "code.gitea.io/gitea/models/organization" repo_model "code.gitea.io/gitea/models/repo" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/lfs" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/migration" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" ) -type Repository = git.Repository +/* +GitHub, GitLab, Gogs: *.wiki.git +BitBucket: *.git/wiki +*/ +var commonWikiURLSuffixes = []string{".wiki.git", ".git/wiki"} -// OpenRepository opens the repository at the given relative path with the provided context. -func OpenRepository(ctx context.Context, repoPath *repo_model.Repository) (*Repository, error) { - return git.OpenRepository(ctx, repoPath.RepoPath()) +// WikiRemoteURL returns accessible repository URL for wiki if exists. +// Otherwise, it returns an empty string. +func WikiRemoteURL(ctx context.Context, remote string) string { + remote = strings.TrimSuffix(remote, ".git") + for _, suffix := range commonWikiURLSuffixes { + wikiURL := remote + suffix + if git.IsRepoURLAccessible(ctx, wikiURL) { + return wikiURL + } + } + return "" } -// DeleteRepository deletes the repository at the given relative path with the provided context. -func DeleteRepository(ctx context.Context, repo *repo_model.Repository) error { - if err := util.RemoveAll(repo.RepoPath()); err != nil { - return fmt.Errorf("Failed to remove %s: %w", repo.FullName(), err) +// MigrateRepositoryGitData starts migrating git related data after created migrating repository +func MigrateRepositoryGitData(ctx context.Context, u *user_model.User, + repo *repo_model.Repository, opts migration.MigrateOptions, + httpTransport *http.Transport, +) (*repo_model.Repository, error) { + repoPath := repo_model.RepoPath(u.Name, opts.RepoName) + + if u.IsOrganization() { + t, err := organization.OrgFromUser(u).GetOwnerTeam(ctx) + 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 = util.RemoveAll(repoPath); err != nil { + return repo, fmt.Errorf("Failed to remove %s: %w", repoPath, err) + } + + if err = git.Clone(ctx, opts.CloneAddr, repoPath, git.CloneRepoOptions{ + Mirror: true, + Quiet: true, + Timeout: migrateTimeout, + SkipTLSVerify: setting.Migrations.SkipTLSVerify, + }); err != nil { + if errors.Is(err, context.DeadlineExceeded) { + return repo, fmt.Errorf("Clone timed out. Consider increasing [git.timeout] MIGRATE in app.ini. Underlying Error: %w", err) + } + return repo, fmt.Errorf("Clone: %w", err) + } + + if err := git.WriteCommitGraph(ctx, repoPath); err != nil { + return repo, err + } + + if opts.Wiki { + wikiPath := repo_model.WikiPath(u.Name, opts.RepoName) + wikiRemotePath := WikiRemoteURL(ctx, opts.CloneAddr) + if len(wikiRemotePath) > 0 { + if err := util.RemoveAll(wikiPath); err != nil { + return repo, fmt.Errorf("Failed to remove %s: %w", wikiPath, err) + } + + if err := git.Clone(ctx, wikiRemotePath, wikiPath, git.CloneRepoOptions{ + Mirror: true, + Quiet: true, + Timeout: migrateTimeout, + Branch: "master", + SkipTLSVerify: setting.Migrations.SkipTLSVerify, + }); err != nil { + log.Warn("Clone wiki: %v", err) + if err := util.RemoveAll(wikiPath); err != nil { + return repo, fmt.Errorf("Failed to remove %s: %w", wikiPath, err) + } + } else { + if err := git.WriteCommitGraph(ctx, wikiPath); err != nil { + return repo, err + } + } + } + } + + if repo.OwnerID == u.ID { + repo.Owner = u + } + + if err = CheckDaemonExportOK(ctx, repo); err != nil { + return repo, fmt.Errorf("checkDaemonExportOK: %w", err) + } + + if stdout, _, err := git.NewCommand(ctx, "update-server-info"). + SetDescription(fmt.Sprintf("MigrateRepositoryGitData(git update-server-info): %s", repoPath)). + RunStdString(&git.RunOpts{Dir: repoPath}); err != nil { + log.Error("MigrateRepositoryGitData(git update-server-info) in %v: Stdout: %s\nError: %v", repo, stdout, err) + return repo, fmt.Errorf("error in MigrateRepositoryGitData(git update-server-info): %w", err) + } + + gitRepo, err := git.OpenRepository(ctx, repoPath) + if err != nil { + return repo, fmt.Errorf("OpenRepository: %w", err) + } + defer gitRepo.Close() + + repo.IsEmpty, err = gitRepo.IsEmpty() + if err != nil { + return repo, fmt.Errorf("git.IsEmpty: %w", err) + } + + if !repo.IsEmpty { + if len(repo.DefaultBranch) == 0 { + // Try to get HEAD branch and set it as default branch. + headBranch, err := gitRepo.GetHEADBranch() + if err != nil { + return repo, fmt.Errorf("GetHEADBranch: %w", err) + } + if headBranch != nil { + repo.DefaultBranch = headBranch.Name + } + } + + if _, err := SyncRepoBranchesWithRepo(ctx, repo, gitRepo, u.ID); err != nil { + return repo, fmt.Errorf("SyncRepoBranchesWithRepo: %v", err) + } + + if !opts.Releases { + // note: this will greatly improve release (tag) sync + // for pull-mirrors with many tags + repo.IsMirror = opts.Mirror + if err = SyncReleasesWithTags(ctx, repo, gitRepo); err != nil { + log.Error("Failed to synchronize tags to releases for repository: %v", err) + } + } + + if opts.LFS { + endpoint := lfs.DetermineEndpoint(opts.CloneAddr, opts.LFSEndpoint) + lfsClient := lfs.NewClient(endpoint, httpTransport) + if err = StoreMissingLfsObjectsInRepository(ctx, repo, gitRepo, lfsClient); err != nil { + log.Error("Failed to store missing LFS objects for repository: %v", err) + } + } } + + ctx, committer, err := db.TxContext(ctx) + if err != nil { + return nil, err + } + defer committer.Close() + + if opts.Mirror { + remoteAddress, err := util.SanitizeURL(opts.CloneAddr) + if err != nil { + return repo, err + } + mirrorModel := repo_model.Mirror{ + RepoID: repo.ID, + Interval: setting.Mirror.DefaultInterval, + EnablePrune: true, + NextUpdateUnix: timeutil.TimeStampNow().AddDuration(setting.Mirror.DefaultInterval), + LFS: opts.LFS, + RemoteAddress: remoteAddress, + } + if opts.LFS { + mirrorModel.LFSEndpoint = opts.LFSEndpoint + } + + if opts.MirrorInterval != "" { + parsedInterval, err := time.ParseDuration(opts.MirrorInterval) + if err != nil { + log.Error("Failed to set Interval: %v", err) + return repo, err + } + if parsedInterval == 0 { + mirrorModel.Interval = 0 + mirrorModel.NextUpdateUnix = 0 + } else if parsedInterval < setting.Mirror.MinInterval { + err := fmt.Errorf("interval %s is set below Minimum Interval of %s", parsedInterval, setting.Mirror.MinInterval) + log.Error("Interval: %s is too frequent", opts.MirrorInterval) + return repo, err + } else { + mirrorModel.Interval = parsedInterval + mirrorModel.NextUpdateUnix = timeutil.TimeStampNow().AddDuration(parsedInterval) + } + } + + if err = repo_model.InsertMirror(ctx, &mirrorModel); err != nil { + return repo, fmt.Errorf("InsertOne: %w", err) + } + + repo.IsMirror = true + if err = UpdateRepository(ctx, repo, false); err != nil { + return nil, err + } + + // this is necessary for sync local tags from remote + configName := fmt.Sprintf("remote.%s.fetch", mirrorModel.GetRemoteName()) + if stdout, _, err := git.NewCommand(ctx, "config"). + AddOptionValues("--add", configName, `+refs/tags/*:refs/tags/*`). + RunStdString(&git.RunOpts{Dir: repoPath}); err != nil { + log.Error("MigrateRepositoryGitData(git config --add +refs/tags/*:refs/tags/*) in %v: Stdout: %s\nError: %v", repo, stdout, err) + return repo, fmt.Errorf("error in MigrateRepositoryGitData(git config --add +refs/tags/*:refs/tags/*): %w", err) + } + } else { + if err = UpdateRepoSize(ctx, repo); err != nil { + log.Error("Failed to update size for repository: %v", err) + } + if repo, err = CleanUpMigrateInfo(ctx, repo); err != nil { + return nil, err + } + } + + return repo, committer.Commit() +} + +// cleanUpMigrateGitConfig removes mirror info which prevents "push --all". +// This also removes possible user credentials. +func cleanUpMigrateGitConfig(ctx context.Context, repoPath string) error { + cmd := git.NewCommand(ctx, "remote", "rm", "origin") + // if the origin does not exist + _, stderr, err := cmd.RunStdString(&git.RunOpts{ + Dir: repoPath, + }) + if err != nil && !strings.HasPrefix(stderr, "fatal: No such remote") { + return err + } + return nil +} + +// CleanUpMigrateInfo finishes migrating repository and/or wiki with things that don't need to be done for mirrors. +func CleanUpMigrateInfo(ctx context.Context, repo *repo_model.Repository) (*repo_model.Repository, error) { + repoPath := repo.RepoPath() + if err := CreateDelegateHooks(repoPath); err != nil { + return repo, fmt.Errorf("createDelegateHooks: %w", err) + } + if repo.HasWiki() { + if err := CreateDelegateHooks(repo.WikiPath()); err != nil { + return repo, fmt.Errorf("createDelegateHooks.(wiki): %w", err) + } + } + + _, _, err := git.NewCommand(ctx, "remote", "rm", "origin").RunStdString(&git.RunOpts{Dir: repoPath}) + if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") { + return repo, fmt.Errorf("CleanUpMigrateInfo: %w", err) + } + + if repo.HasWiki() { + if err := cleanUpMigrateGitConfig(ctx, repo.WikiPath()); err != nil { + return repo, fmt.Errorf("cleanUpMigrateGitConfig (wiki): %w", err) + } + } + + return repo, UpdateRepository(ctx, repo, false) +} + +// SyncRepoTags synchronizes releases table with repository tags +func SyncRepoTags(ctx context.Context, repoID int64) error { + repo, err := repo_model.GetRepositoryByID(ctx, repoID) + if err != nil { + return err + } + + gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) + if err != nil { + return err + } + defer gitRepo.Close() + + return SyncReleasesWithTags(ctx, repo, gitRepo) +} + +// SyncReleasesWithTags synchronizes release table with repository tags +func SyncReleasesWithTags(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository) error { + log.Debug("SyncReleasesWithTags: in Repo[%d:%s/%s]", repo.ID, repo.OwnerName, repo.Name) + + // optimized procedure for pull-mirrors which saves a lot of time (in + // particular for repos with many tags). + if repo.IsMirror { + return pullMirrorReleaseSync(ctx, repo, gitRepo) + } + + existingRelTags := make(container.Set[string]) + opts := repo_model.FindReleasesOptions{ + IncludeDrafts: true, + IncludeTags: true, + ListOptions: db.ListOptions{PageSize: 50}, + RepoID: repo.ID, + } + for page := 1; ; page++ { + opts.Page = page + rels, err := db.Find[repo_model.Release](gitRepo.Ctx, opts) + if err != nil { + return fmt.Errorf("unable to GetReleasesByRepoID in Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, 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("unable to GetTagCommitID for %q in Repo[%d:%s/%s]: %w", rel.TagName, repo.ID, repo.OwnerName, repo.Name, err) + } + if git.IsErrNotExist(err) || commitID != rel.Sha1 { + if err := repo_model.PushUpdateDeleteTag(ctx, repo, rel.TagName); err != nil { + return fmt.Errorf("unable to PushUpdateDeleteTag: %q in Repo[%d:%s/%s]: %w", rel.TagName, repo.ID, repo.OwnerName, repo.Name, err) + } + } else { + existingRelTags.Add(strings.ToLower(rel.TagName)) + } + } + } + + _, err := gitRepo.WalkReferences(git.ObjectTag, 0, 0, func(sha1, refname string) error { + tagName := strings.TrimPrefix(refname, git.TagPrefix) + if existingRelTags.Contains(strings.ToLower(tagName)) { + return nil + } + + if err := PushUpdateAddTag(ctx, repo, gitRepo, tagName, sha1, refname); err != nil { + return fmt.Errorf("unable to PushUpdateAddTag: %q to Repo[%d:%s/%s]: %w", tagName, repo.ID, repo.OwnerName, repo.Name, err) + } + + return nil + }) + return err +} + +// PushUpdateAddTag must be called for any push actions to add tag +func PushUpdateAddTag(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, tagName, sha1, refname string) error { + tag, err := gitRepo.GetTagWithID(sha1, tagName) + if err != nil { + return fmt.Errorf("unable to GetTag: %w", err) + } + commit, err := tag.Commit(gitRepo) + if err != nil { + return fmt.Errorf("unable to get tag Commit: %w", err) + } + + sig := tag.Tagger + if sig == nil { + sig = commit.Author + } + if sig == nil { + sig = commit.Committer + } + + var author *user_model.User + createdAt := time.Unix(1, 0) + + if sig != nil { + author, err = user_model.GetUserByEmail(ctx, sig.Email) + if err != nil && !user_model.IsErrUserNotExist(err) { + return fmt.Errorf("unable to GetUserByEmail for %q: %w", sig.Email, err) + } + createdAt = sig.When + } + + commitsCount, err := commit.CommitsCount() + if err != nil { + return fmt.Errorf("unable to get CommitsCount: %w", err) + } + + rel := repo_model.Release{ + RepoID: repo.ID, + TagName: tagName, + LowerTagName: strings.ToLower(tagName), + Sha1: commit.ID.String(), + NumCommits: commitsCount, + CreatedUnix: timeutil.TimeStamp(createdAt.Unix()), + IsTag: true, + } + if author != nil { + rel.PublisherID = author.ID + } + + return repo_model.SaveOrUpdateTag(ctx, repo, &rel) +} + +// StoreMissingLfsObjectsInRepository downloads missing LFS objects +func StoreMissingLfsObjectsInRepository(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, lfsClient lfs.Client) error { + contentStore := lfs.NewContentStore() + + pointerChan := make(chan lfs.PointerBlob) + errChan := make(chan error, 1) + go lfs.SearchPointerBlobs(ctx, gitRepo, pointerChan, errChan) + + downloadObjects := func(pointers []lfs.Pointer) error { + err := lfsClient.Download(ctx, pointers, func(p lfs.Pointer, content io.ReadCloser, objectError error) error { + if objectError != nil { + return objectError + } + + defer content.Close() + + _, err := git_model.NewLFSMetaObject(ctx, repo.ID, p) + if err != nil { + log.Error("Repo[%-v]: Error creating LFS meta object %-v: %v", repo, p, err) + return err + } + + if err := contentStore.Put(p, content); err != nil { + log.Error("Repo[%-v]: Error storing content for LFS meta object %-v: %v", repo, p, err) + if _, err2 := git_model.RemoveLFSMetaObjectByOid(ctx, repo.ID, p.Oid); err2 != nil { + log.Error("Repo[%-v]: Error removing LFS meta object %-v: %v", repo, p, err2) + } + return err + } + return nil + }) + if err != nil { + select { + case <-ctx.Done(): + return nil + default: + } + } + return err + } + + var batch []lfs.Pointer + for pointerBlob := range pointerChan { + meta, err := git_model.GetLFSMetaObjectByOid(ctx, repo.ID, pointerBlob.Oid) + if err != nil && err != git_model.ErrLFSObjectNotExist { + log.Error("Repo[%-v]: Error querying LFS meta object %-v: %v", repo, pointerBlob.Pointer, err) + return err + } + if meta != nil { + log.Trace("Repo[%-v]: Skipping unknown LFS meta object %-v", repo, pointerBlob.Pointer) + continue + } + + log.Trace("Repo[%-v]: LFS object %-v not present in repository", repo, pointerBlob.Pointer) + + exist, err := contentStore.Exists(pointerBlob.Pointer) + if err != nil { + log.Error("Repo[%-v]: Error checking if LFS object %-v exists: %v", repo, pointerBlob.Pointer, err) + return err + } + + if exist { + log.Trace("Repo[%-v]: LFS object %-v already present; creating meta object", repo, pointerBlob.Pointer) + _, err := git_model.NewLFSMetaObject(ctx, repo.ID, pointerBlob.Pointer) + if err != nil { + log.Error("Repo[%-v]: Error creating LFS meta object %-v: %v", repo, pointerBlob.Pointer, err) + return err + } + } else { + if setting.LFS.MaxFileSize > 0 && pointerBlob.Size > setting.LFS.MaxFileSize { + log.Info("Repo[%-v]: LFS object %-v download denied because of LFS_MAX_FILE_SIZE=%d < size %d", repo, pointerBlob.Pointer, setting.LFS.MaxFileSize, pointerBlob.Size) + continue + } + + batch = append(batch, pointerBlob.Pointer) + if len(batch) >= lfsClient.BatchSize() { + if err := downloadObjects(batch); err != nil { + return err + } + batch = nil + } + } + } + if len(batch) > 0 { + if err := downloadObjects(batch); err != nil { + return err + } + } + + err, has := <-errChan + if has { + log.Error("Repo[%-v]: Error enumerating LFS objects for repository: %v", repo, err) + return err + } + + return nil +} + +// pullMirrorReleaseSync is a pull-mirror specific tag<->release table +// synchronization which overwrites all Releases from the repository tags. This +// can be relied on since a pull-mirror is always identical to its +// upstream. Hence, after each sync we want the pull-mirror release set to be +// identical to the upstream tag set. This is much more efficient for +// repositories like https://github.com/vim/vim (with over 13000 tags). +func pullMirrorReleaseSync(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository) error { + log.Trace("pullMirrorReleaseSync: rebuilding releases for pull-mirror Repo[%d:%s/%s]", repo.ID, repo.OwnerName, repo.Name) + tags, numTags, err := gitRepo.GetTagInfos(0, 0) + if err != nil { + return fmt.Errorf("unable to GetTagInfos in pull-mirror Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, err) + } + err = db.WithTx(ctx, func(ctx context.Context) error { + // + // clear out existing releases + // + if _, err := db.DeleteByBean(ctx, &repo_model.Release{RepoID: repo.ID}); err != nil { + return fmt.Errorf("unable to clear releases for pull-mirror Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, err) + } + // + // make release set identical to upstream tags + // + for _, tag := range tags { + release := repo_model.Release{ + RepoID: repo.ID, + TagName: tag.Name, + LowerTagName: strings.ToLower(tag.Name), + Sha1: tag.Object.String(), + // NOTE: ignored, since NumCommits are unused + // for pull-mirrors (only relevant when + // displaying releases, IsTag: false) + NumCommits: -1, + CreatedUnix: timeutil.TimeStamp(tag.Tagger.When.Unix()), + IsTag: true, + } + if err := db.Insert(ctx, release); err != nil { + return fmt.Errorf("unable insert tag %s for pull-mirror Repo[%d:%s/%s]: %w", tag.Name, repo.ID, repo.OwnerName, repo.Name, err) + } + } + return nil + }) + if err != nil { + return fmt.Errorf("unable to rebuild release table for pull-mirror Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, err) + } + + log.Trace("pullMirrorReleaseSync: done rebuilding %d releases", numTags) return nil } diff --git a/modules/repository/tag.go b/modules/repository/tag.go deleted file mode 100644 index e51197d883184..0000000000000 --- a/modules/repository/tag.go +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright 2024 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package repository - -import ( - "context" - "fmt" - "strings" - "time" - - "code.gitea.io/gitea/models/db" - repo_model "code.gitea.io/gitea/models/repo" - user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/container" - "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/timeutil" -) - -// SyncRepoTags synchronizes releases table with repository tags -func SyncRepoTags(ctx context.Context, repoID int64) error { - repo, err := repo_model.GetRepositoryByID(ctx, repoID) - if err != nil { - return err - } - - gitRepo, err := OpenRepository(ctx, repo) - if err != nil { - return err - } - defer gitRepo.Close() - - return SyncReleasesWithTags(ctx, repo, gitRepo) -} - -// SyncReleasesWithTags synchronizes release table with repository tags -func SyncReleasesWithTags(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository) error { - log.Debug("SyncReleasesWithTags: in Repo[%d:%s/%s]", repo.ID, repo.OwnerName, repo.Name) - - // optimized procedure for pull-mirrors which saves a lot of time (in - // particular for repos with many tags). - if repo.IsMirror { - return pullMirrorReleaseSync(ctx, repo, gitRepo) - } - - existingRelTags := make(container.Set[string]) - opts := repo_model.FindReleasesOptions{ - IncludeDrafts: true, - IncludeTags: true, - ListOptions: db.ListOptions{PageSize: 50}, - RepoID: repo.ID, - } - for page := 1; ; page++ { - opts.Page = page - rels, err := db.Find[repo_model.Release](gitRepo.Ctx, opts) - if err != nil { - return fmt.Errorf("unable to GetReleasesByRepoID in Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, 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("unable to GetTagCommitID for %q in Repo[%d:%s/%s]: %w", rel.TagName, repo.ID, repo.OwnerName, repo.Name, err) - } - if git.IsErrNotExist(err) || commitID != rel.Sha1 { - if err := repo_model.PushUpdateDeleteTag(ctx, repo, rel.TagName); err != nil { - return fmt.Errorf("unable to PushUpdateDeleteTag: %q in Repo[%d:%s/%s]: %w", rel.TagName, repo.ID, repo.OwnerName, repo.Name, err) - } - } else { - existingRelTags.Add(strings.ToLower(rel.TagName)) - } - } - } - - _, err := gitRepo.WalkReferences(git.ObjectTag, 0, 0, func(sha1, refname string) error { - tagName := strings.TrimPrefix(refname, git.TagPrefix) - if existingRelTags.Contains(strings.ToLower(tagName)) { - return nil - } - - if err := PushUpdateAddTag(ctx, repo, gitRepo, tagName, sha1, refname); err != nil { - return fmt.Errorf("unable to PushUpdateAddTag: %q to Repo[%d:%s/%s]: %w", tagName, repo.ID, repo.OwnerName, repo.Name, err) - } - - return nil - }) - return err -} - -// PushUpdateAddTag must be called for any push actions to add tag -func PushUpdateAddTag(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, tagName, sha1, refname string) error { - tag, err := gitRepo.GetTagWithID(sha1, tagName) - if err != nil { - return fmt.Errorf("unable to GetTag: %w", err) - } - commit, err := tag.Commit(gitRepo) - if err != nil { - return fmt.Errorf("unable to get tag Commit: %w", err) - } - - sig := tag.Tagger - if sig == nil { - sig = commit.Author - } - if sig == nil { - sig = commit.Committer - } - - var author *user_model.User - createdAt := time.Unix(1, 0) - - if sig != nil { - author, err = user_model.GetUserByEmail(ctx, sig.Email) - if err != nil && !user_model.IsErrUserNotExist(err) { - return fmt.Errorf("unable to GetUserByEmail for %q: %w", sig.Email, err) - } - createdAt = sig.When - } - - commitsCount, err := commit.CommitsCount() - if err != nil { - return fmt.Errorf("unable to get CommitsCount: %w", err) - } - - rel := repo_model.Release{ - RepoID: repo.ID, - TagName: tagName, - LowerTagName: strings.ToLower(tagName), - Sha1: commit.ID.String(), - NumCommits: commitsCount, - CreatedUnix: timeutil.TimeStamp(createdAt.Unix()), - IsTag: true, - } - if author != nil { - rel.PublisherID = author.ID - } - - return repo_model.SaveOrUpdateTag(ctx, repo, &rel) -} - -// pullMirrorReleaseSync is a pull-mirror specific tag<->release table -// synchronization which overwrites all Releases from the repository tags. This -// can be relied on since a pull-mirror is always identical to its -// upstream. Hence, after each sync we want the pull-mirror release set to be -// identical to the upstream tag set. This is much more efficient for -// repositories like https://github.com/vim/vim (with over 13000 tags). -func pullMirrorReleaseSync(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository) error { - log.Trace("pullMirrorReleaseSync: rebuilding releases for pull-mirror Repo[%d:%s/%s]", repo.ID, repo.OwnerName, repo.Name) - tags, numTags, err := gitRepo.GetTagInfos(0, 0) - if err != nil { - return fmt.Errorf("unable to GetTagInfos in pull-mirror Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, err) - } - err = db.WithTx(ctx, func(ctx context.Context) error { - // - // clear out existing releases - // - if _, err := db.DeleteByBean(ctx, &repo_model.Release{RepoID: repo.ID}); err != nil { - return fmt.Errorf("unable to clear releases for pull-mirror Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, err) - } - // - // make release set identical to upstream tags - // - for _, tag := range tags { - release := repo_model.Release{ - RepoID: repo.ID, - TagName: tag.Name, - LowerTagName: strings.ToLower(tag.Name), - Sha1: tag.Object.String(), - // NOTE: ignored, since NumCommits are unused - // for pull-mirrors (only relevant when - // displaying releases, IsTag: false) - NumCommits: -1, - CreatedUnix: timeutil.TimeStamp(tag.Tagger.When.Unix()), - IsTag: true, - } - if err := db.Insert(ctx, release); err != nil { - return fmt.Errorf("unable insert tag %s for pull-mirror Repo[%d:%s/%s]: %w", tag.Name, repo.ID, repo.OwnerName, repo.Name, err) - } - } - return nil - }) - if err != nil { - return fmt.Errorf("unable to rebuild release table for pull-mirror Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, err) - } - - log.Trace("pullMirrorReleaseSync: done rebuilding %d releases", numTags) - return nil -} diff --git a/modules/repository/wiki.go b/modules/repository/wiki.go deleted file mode 100644 index 65a7b676ffa23..0000000000000 --- a/modules/repository/wiki.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2024 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package repository - -import ( - "context" - "strings" - - repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/modules/git" -) - -/* -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(ctx context.Context, remote string) string { - remote = strings.TrimSuffix(remote, ".git") - for _, suffix := range commonWikiURLSuffixes { - wikiURL := remote + suffix - if git.IsRepoURLAccessible(ctx, wikiURL) { - return wikiURL - } - } - return "" -} - -// OpenWikiRepository opens the repository at the given relative path with the provided context. -func OpenWikiRepository(ctx context.Context, repoPath *repo_model.Repository) (*Repository, error) { - return git.OpenRepository(ctx, repoPath.WikiPath()) -} diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index 5697641303d0f..bd02a8afc4340 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -16,6 +16,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" repo_module "code.gitea.io/gitea/modules/repository" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" @@ -643,7 +644,7 @@ func CreateBranchProtection(ctx *context.APIContext) { } else { if !isPlainRule { if ctx.Repo.GitRepo == nil { - ctx.Repo.GitRepo, err = repo_module.OpenRepository(ctx, ctx.Repo.Repository) + ctx.Repo.GitRepo, err = gitrepo.OpenRepository(ctx, ctx.Repo.Repository) if err != nil { ctx.Error(http.StatusInternalServerError, "OpenRepository", err) return @@ -920,7 +921,7 @@ func EditBranchProtection(ctx *context.APIContext) { } else { if !isPlainRule { if ctx.Repo.GitRepo == nil { - ctx.Repo.GitRepo, err = repo_module.OpenRepository(ctx, ctx.Repo.Repository) + ctx.Repo.GitRepo, err = gitrepo.OpenRepository(ctx, ctx.Repo.Repository) if err != nil { ctx.Error(http.StatusInternalServerError, "OpenRepository", err) return diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go index bc992404f746a..065d6bf8b2c38 100644 --- a/routers/api/v1/repo/file.go +++ b/routers/api/v1/repo/file.go @@ -21,10 +21,10 @@ import ( "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/httpcache" "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" - repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/storage" api "code.gitea.io/gitea/modules/structs" @@ -281,7 +281,7 @@ func GetArchive(ctx *context.APIContext) { // "$ref": "#/responses/notFound" if ctx.Repo.GitRepo == nil { - gitRepo, err := repo_module.OpenRepository(ctx, ctx.Repo.Repository) + gitRepo, err := gitrepo.OpenRepository(ctx, ctx.Repo.Repository) if err != nil { ctx.Error(http.StatusInternalServerError, "OpenRepository", err) return diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index a67f9479e4fc3..7647c88f2a082 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -23,8 +23,8 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" - repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/timeutil" @@ -907,7 +907,7 @@ func MergePullRequest(ctx *context.APIContext) { if ctx.Repo != nil && ctx.Repo.Repository != nil && ctx.Repo.Repository.ID == pr.HeadRepoID && ctx.Repo.GitRepo != nil { headRepo = ctx.Repo.GitRepo } else { - headRepo, err = repo_module.OpenRepository(ctx, pr.HeadRepo) + headRepo, err = gitrepo.OpenRepository(ctx, pr.HeadRepo) if err != nil { ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.HeadRepo.FullName()), err) return @@ -1005,7 +1005,7 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) headRepo = ctx.Repo.Repository headGitRepo = ctx.Repo.GitRepo } else { - headGitRepo, err = repo_module.OpenRepository(ctx, headRepo) + headGitRepo, err = gitrepo.OpenRepository(ctx, headRepo) if err != nil { ctx.Error(http.StatusInternalServerError, "OpenRepository", err) return nil, nil, nil, nil, "", "" diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 6f975fce9fbeb..2efdccb569901 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -21,6 +21,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/label" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" @@ -718,7 +719,7 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err if ctx.Repo.GitRepo == nil && !repo.IsEmpty { var err error - ctx.Repo.GitRepo, err = repo_module.OpenRepository(ctx, ctx.Repo.Repository) + ctx.Repo.GitRepo, err = gitrepo.OpenRepository(ctx, ctx.Repo.Repository) if err != nil { ctx.Error(http.StatusInternalServerError, "Unable to OpenRepository", err) return err diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 769bfd778b44e..ba3e978a83531 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -12,7 +12,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" - repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" @@ -476,7 +476,7 @@ func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error) // findWikiRepoCommit opens the wiki repo and returns the latest commit, writing to context on error. // The caller is responsible for closing the returned repo again func findWikiRepoCommit(ctx *context.APIContext) (*git.Repository, *git.Commit) { - wikiRepo, err := repo_module.OpenWikiRepository(ctx, ctx.Repo.Repository) + wikiRepo, err := gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository) if err != nil { if git.IsErrNotExist(err) || err.Error() == "no such file or directory" { diff --git a/routers/private/internal_repo.go b/routers/private/internal_repo.go index 0dec1fbcb5697..615239d479d96 100644 --- a/routers/private/internal_repo.go +++ b/routers/private/internal_repo.go @@ -10,9 +10,9 @@ import ( repo_model "code.gitea.io/gitea/models/repo" gitea_context "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/private" - repo_module "code.gitea.io/gitea/modules/repository" ) // This file contains common functions relating to setting the Repository for the internal routes @@ -28,7 +28,7 @@ func RepoAssignment(ctx *gitea_context.PrivateContext) context.CancelFunc { return nil } - gitRepo, err := repo_module.OpenRepository(ctx, repo) + gitRepo, err := gitrepo.OpenRepository(ctx, repo) if err != nil { log.Error("Failed to open repository: %s/%s Error: %v", ownerName, repoName, err) ctx.JSON(http.StatusInternalServerError, private.Response{ diff --git a/routers/web/repo/commit.go b/routers/web/repo/commit.go index 8ff428dbb197f..2b0c5702cdd0f 100644 --- a/routers/web/repo/commit.go +++ b/routers/web/repo/commit.go @@ -22,9 +22,9 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/gitgraph" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" - repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/services/gitdiff" @@ -280,7 +280,7 @@ func Diff(ctx *context.Context) { ) if ctx.Data["PageIsWiki"] != nil { - gitRepo, err = repo_module.OpenWikiRepository(ctx, ctx.Repo.Repository) + gitRepo, err = gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository) if err != nil { ctx.ServerError("Repo.GitRepo.GetCommit", err) return @@ -405,7 +405,7 @@ func Diff(ctx *context.Context) { func RawDiff(ctx *context.Context) { var gitRepo *git.Repository if ctx.Data["PageIsWiki"] != nil { - wikiRepo, err := repo_module.OpenWikiRepository(ctx, ctx.Repo.Repository) + wikiRepo, err := gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository) if err != nil { ctx.ServerError("OpenRepository", err) return diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index c62a34289fd60..97488f99988a3 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -28,9 +28,9 @@ import ( "code.gitea.io/gitea/modules/context" csv_module "code.gitea.io/gitea/modules/csv" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" - repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/typesniffer" @@ -409,7 +409,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo { ci.HeadRepo = ctx.Repo.Repository ci.HeadGitRepo = ctx.Repo.GitRepo } else if has { - ci.HeadGitRepo, err = repo_module.OpenRepository(ctx, ci.HeadRepo) + ci.HeadGitRepo, err = gitrepo.OpenRepository(ctx, ci.HeadRepo) if err != nil { ctx.ServerError("OpenRepository", err) return nil @@ -689,7 +689,7 @@ func PrepareCompareDiff( } func getBranchesAndTagsForRepo(ctx gocontext.Context, repo *repo_model.Repository) (branches, tags []string, err error) { - gitRepo, err := repo_module.OpenRepository(ctx, repo) + gitRepo, err := gitrepo.OpenRepository(ctx, repo) if err != nil { return nil, nil, err } @@ -877,7 +877,7 @@ func ExcerptBlob(ctx *context.Context) { gitRepo := ctx.Repo.GitRepo if ctx.FormBool("wiki") { var err error - gitRepo, err = repo_module.OpenWikiRepository(ctx, ctx.Repo.Repository) + gitRepo, err = gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository) if err != nil { ctx.ServerError("OpenRepository", err) return diff --git a/routers/web/repo/editor_test.go b/routers/web/repo/editor_test.go index ae21bd4e7f36f..c28c3ef1d632d 100644 --- a/routers/web/repo/editor_test.go +++ b/routers/web/repo/editor_test.go @@ -9,7 +9,7 @@ import ( "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/contexttest" "code.gitea.io/gitea/modules/git" - repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/gitrepo" "github.com/stretchr/testify/assert" ) @@ -67,7 +67,7 @@ func TestGetClosestParentWithFiles(t *testing.T) { repo := ctx.Repo.Repository branch := repo.DefaultBranch - gitRepo, _ := repo_module.OpenRepository(git.DefaultContext, repo) + gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo) defer gitRepo.Close() commit, _ := gitRepo.GetBranchCommit(branch) var expectedTreePath string // Should return the root dir, empty string, since there are no subdirs in this repo diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 0d96e3f156078..b265cf47548bc 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -29,9 +29,9 @@ import ( "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" issue_template "code.gitea.io/gitea/modules/issue/template" "code.gitea.io/gitea/modules/log" - repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/upload" @@ -531,7 +531,7 @@ func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.C if pull.BaseRepoID == ctx.Repo.Repository.ID && ctx.Repo.GitRepo != nil { baseGitRepo = ctx.Repo.GitRepo } else { - baseGitRepo, err := repo_module.OpenRepository(ctx, pull.BaseRepo) + baseGitRepo, err := gitrepo.OpenRepository(ctx, pull.BaseRepo) if err != nil { ctx.ServerError("OpenRepository", err) return nil @@ -583,7 +583,7 @@ func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.C var headBranchSha string // HeadRepo may be missing if pull.HeadRepo != nil { - headGitRepo, err := repo_module.OpenRepository(ctx, pull.HeadRepo) + headGitRepo, err := gitrepo.OpenRepository(ctx, pull.HeadRepo) if err != nil { ctx.ServerError("OpenRepository", err) return nil @@ -1315,7 +1315,7 @@ func MergePullRequest(ctx *context.Context) { if ctx.Repo != nil && ctx.Repo.Repository != nil && pr.HeadRepoID == ctx.Repo.Repository.ID && ctx.Repo.GitRepo != nil { headRepo = ctx.Repo.GitRepo } else { - headRepo, err = repo_module.OpenRepository(ctx, pr.HeadRepo) + headRepo, err = gitrepo.OpenRepository(ctx, pr.HeadRepo) if err != nil { ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.HeadRepo.FullName()), err) return @@ -1538,7 +1538,7 @@ func CleanUpPullRequest(ctx *context.Context) { gitBaseRepo = ctx.Repo.GitRepo } else { // If not just open it - gitBaseRepo, err = repo_module.OpenRepository(ctx, pr.BaseRepo) + gitBaseRepo, err = gitrepo.OpenRepository(ctx, pr.BaseRepo) if err != nil { ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.BaseRepo.FullName()), err) return @@ -1553,7 +1553,7 @@ func CleanUpPullRequest(ctx *context.Context) { gitRepo = ctx.Repo.GitRepo } else if pr.BaseRepoID != pr.HeadRepoID { // Otherwise just load it up - gitRepo, err = repo_module.OpenRepository(ctx, pr.HeadRepo) + gitRepo, err = gitrepo.OpenRepository(ctx, pr.HeadRepo) if err != nil { ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.HeadRepo.FullName()), err) return diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go index f665c784fd738..5e7b971e67b72 100644 --- a/routers/web/repo/wiki.go +++ b/routers/web/repo/wiki.go @@ -20,10 +20,10 @@ import ( "code.gitea.io/gitea/modules/charset" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/markup/markdown" - repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" @@ -93,7 +93,7 @@ func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error) } func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, error) { - wikiRepo, err := repo_module.OpenWikiRepository(ctx, ctx.Repo.Repository) + wikiRepo, err := gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository) if err != nil { ctx.ServerError("OpenRepository", err) return nil, nil, err diff --git a/routers/web/repo/wiki_test.go b/routers/web/repo/wiki_test.go index 629b2f0248bba..d3decdae2deff 100644 --- a/routers/web/repo/wiki_test.go +++ b/routers/web/repo/wiki_test.go @@ -13,7 +13,7 @@ import ( "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/contexttest" "code.gitea.io/gitea/modules/git" - repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/services/forms" wiki_service "code.gitea.io/gitea/services/wiki" @@ -27,7 +27,7 @@ const ( ) func wikiEntry(t *testing.T, repo *repo_model.Repository, wikiName wiki_service.WebPath) *git.TreeEntry { - wikiRepo, err := repo_module.OpenWikiRepository(git.DefaultContext, repo) + wikiRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo) assert.NoError(t, err) defer wikiRepo.Close() commit, err := wikiRepo.GetBranchCommit("master") diff --git a/routers/web/shared/user/header.go b/routers/web/shared/user/header.go index cd99a734e9c72..a2c0abb47e4a1 100644 --- a/routers/web/shared/user/header.go +++ b/routers/web/shared/user/header.go @@ -13,10 +13,10 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/markup/markdown" - repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" ) @@ -91,7 +91,7 @@ func FindUserProfileReadme(ctx *context.Context, doer *user_model.User) (profile if err == nil { perm, err := access_model.GetUserRepoPermission(ctx, profileDbRepo, doer) if err == nil && !profileDbRepo.IsEmpty && perm.CanRead(unit.TypeCode) { - if profileGitRepo, err = repo_module.OpenRepository(ctx, profileDbRepo); err != nil { + if profileGitRepo, err = gitrepo.OpenRepository(ctx, profileDbRepo); err != nil { log.Error("FindUserProfileReadme failed to OpenRepository: %v", err) } else { if commit, err := profileGitRepo.GetBranchCommit(profileDbRepo.DefaultBranch); err != nil { diff --git a/services/actions/notifier_helper.go b/services/actions/notifier_helper.go index 5458de1793145..9900de3d2ecdd 100644 --- a/services/actions/notifier_helper.go +++ b/services/actions/notifier_helper.go @@ -20,9 +20,9 @@ import ( user_model "code.gitea.io/gitea/models/user" actions_module "code.gitea.io/gitea/modules/actions" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" - repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" webhook_module "code.gitea.io/gitea/modules/webhook" @@ -129,7 +129,7 @@ func notify(ctx context.Context, input *notifyInput) error { return nil } - gitRepo, err := repo_module.OpenRepository(context.Background(), input.Repo) + gitRepo, err := gitrepo.OpenRepository(context.Background(), input.Repo) if err != nil { return fmt.Errorf("git.OpenRepository: %w", err) } diff --git a/services/automerge/automerge.go b/services/automerge/automerge.go index 54cf136a47332..bd427bef9f731 100644 --- a/services/automerge/automerge.go +++ b/services/automerge/automerge.go @@ -17,11 +17,11 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/queue" - repo_module "code.gitea.io/gitea/modules/repository" pull_service "code.gitea.io/gitea/services/pull" ) @@ -112,7 +112,7 @@ func MergeScheduledPullRequest(ctx context.Context, sha string, repo *repo_model } func getPullRequestsByHeadSHA(ctx context.Context, sha string, repo *repo_model.Repository, filter func(*issues_model.PullRequest) bool) (map[int64]*issues_model.PullRequest, error) { - gitRepo, err := repo_module.OpenRepository(ctx, repo) + gitRepo, err := gitrepo.OpenRepository(ctx, repo) if err != nil { return nil, err } @@ -191,7 +191,7 @@ func handlePull(pullID int64, sha string) { return } - headGitRepo, err := repo_module.OpenRepository(ctx, pr.HeadRepo) + headGitRepo, err := gitrepo.OpenRepository(ctx, pr.HeadRepo) if err != nil { log.Error("OpenRepository %-v: %v", pr.HeadRepo, err) return @@ -247,7 +247,7 @@ func handlePull(pullID int64, sha string) { return } - baseGitRepo, err = repo_module.OpenRepository(ctx, pr.BaseRepo) + baseGitRepo, err = gitrepo.OpenRepository(ctx, pr.BaseRepo) if err != nil { log.Error("OpenRepository %-v: %v", pr.BaseRepo, err) return diff --git a/services/convert/pull.go b/services/convert/pull.go index a12457086517a..6d98121ed54c4 100644 --- a/services/convert/pull.go +++ b/services/convert/pull.go @@ -12,8 +12,8 @@ import ( access_model "code.gitea.io/gitea/models/perm/access" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" - repo_module "code.gitea.io/gitea/modules/repository" api "code.gitea.io/gitea/modules/structs" ) @@ -102,7 +102,7 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u apiPullRequest.Closed = pr.Issue.ClosedUnix.AsTimePtr() } - gitRepo, err := repo_module.OpenRepository(ctx, pr.BaseRepo) + gitRepo, err := gitrepo.OpenRepository(ctx, pr.BaseRepo) if err != nil { log.Error("OpenRepository[%s]: %v", pr.BaseRepo.RepoPath(), err) return nil @@ -128,7 +128,7 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u } if pr.Flow == issues_model.PullRequestFlowAGit { - gitRepo, err := repo_module.OpenRepository(ctx, pr.BaseRepo) + gitRepo, err := gitrepo.OpenRepository(ctx, pr.BaseRepo) if err != nil { log.Error("OpenRepository[%s]: %v", pr.GetGitRefName(), err) return nil @@ -155,7 +155,7 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u apiPullRequest.Head.RepoID = pr.HeadRepo.ID apiPullRequest.Head.Repository = ToRepo(ctx, pr.HeadRepo, p) - headGitRepo, err := repo_module.OpenRepository(ctx, pr.HeadRepo) + headGitRepo, err := gitrepo.OpenRepository(ctx, pr.HeadRepo) if err != nil { log.Error("OpenRepository[%s]: %v", pr.HeadRepo.RepoPath(), err) return nil @@ -191,7 +191,7 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u } if len(apiPullRequest.Head.Sha) == 0 && len(apiPullRequest.Head.Ref) != 0 { - baseGitRepo, err := repo_module.OpenRepository(ctx, pr.BaseRepo) + baseGitRepo, err := gitrepo.OpenRepository(ctx, pr.BaseRepo) if err != nil { log.Error("OpenRepository[%s]: %v", pr.BaseRepo.RepoPath(), err) return nil diff --git a/services/doctor/misc.go b/services/doctor/misc.go index ace9f29aa56e2..9300c3a25c9c6 100644 --- a/services/doctor/misc.go +++ b/services/doctor/misc.go @@ -16,9 +16,9 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/repository" - repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" @@ -92,7 +92,7 @@ func checkEnablePushOptions(ctx context.Context, logger log.Logger, autofix bool if err := iterateRepositories(ctx, func(repo *repo_model.Repository) error { numRepos++ - r, err := repo_module.OpenRepository(ctx, repo) + r, err := gitrepo.OpenRepository(ctx, repo) if err != nil { return err } diff --git a/services/issue/issue.go b/services/issue/issue.go index 0194d3a353ad8..265f712e8f5aa 100644 --- a/services/issue/issue.go +++ b/services/issue/issue.go @@ -17,8 +17,8 @@ import ( system_model "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" - repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/storage" notify_service "code.gitea.io/gitea/services/notify" @@ -63,7 +63,7 @@ func PullRequestCodeOwnersReview(ctx context.Context, pull *issues_model.Issue, return err } - repo, err := repo_module.OpenRepository(ctx, pr.BaseRepo) + repo, err := gitrepo.OpenRepository(ctx, pr.BaseRepo) if err != nil { return err } diff --git a/services/migrations/gitea_uploader.go b/services/migrations/gitea_uploader.go index 32d9875c190b0..7b21d9f4d2438 100644 --- a/services/migrations/gitea_uploader.go +++ b/services/migrations/gitea_uploader.go @@ -21,6 +21,7 @@ import ( user_model "code.gitea.io/gitea/models/user" base_module "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/label" "code.gitea.io/gitea/modules/log" base "code.gitea.io/gitea/modules/migration" @@ -139,7 +140,7 @@ func (g *GiteaLocalUploader) CreateRepo(repo *base.Repository, opts base.Migrate if err != nil { return err } - g.gitRepo, err = repo_module.OpenRepository(g.ctx, r) + g.gitRepo, err = gitrepo.OpenRepository(g.ctx, r) return err } diff --git a/services/migrations/gitea_uploader_test.go b/services/migrations/gitea_uploader_test.go index 9593937c3d3b7..c8102c6b8b71b 100644 --- a/services/migrations/gitea_uploader_test.go +++ b/services/migrations/gitea_uploader_test.go @@ -19,10 +19,10 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" base "code.gitea.io/gitea/modules/migration" - repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/modules/util" @@ -250,7 +250,7 @@ func TestGiteaUploadUpdateGitForPullRequest(t *testing.T) { Author: &signature, Message: "Initial Commit", })) - fromGitRepo, err := repo_module.OpenRepository(git.DefaultContext, fromRepo) + fromGitRepo, err := gitrepo.OpenRepository(git.DefaultContext, fromRepo) assert.NoError(t, err) defer fromGitRepo.Close() baseSHA, err := fromGitRepo.GetBranchCommitID(baseRef) @@ -293,7 +293,7 @@ func TestGiteaUploadUpdateGitForPullRequest(t *testing.T) { Author: &signature, Message: "branch2 commit", })) - forkGitRepo, err := repo_module.OpenRepository(git.DefaultContext, forkRepo) + forkGitRepo, err := gitrepo.OpenRepository(git.DefaultContext, forkRepo) assert.NoError(t, err) defer forkGitRepo.Close() forkHeadSHA, err := forkGitRepo.GetBranchCommitID(forkHeadRef) diff --git a/services/mirror/mirror_pull.go b/services/mirror/mirror_pull.go index 3baaa50ac4774..b2635c5b98518 100644 --- a/services/mirror/mirror_pull.go +++ b/services/mirror/mirror_pull.go @@ -13,6 +13,7 @@ import ( system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" @@ -300,7 +301,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo log.Error("SyncMirrors [repo: %-v]: %v", m.Repo, err) } - gitRepo, err := repo_module.OpenRepository(ctx, m.Repo) + gitRepo, err := gitrepo.OpenRepository(ctx, m.Repo) if err != nil { log.Error("SyncMirrors [repo: %-v]: failed to OpenRepository: %v", m.Repo, err) return nil, false @@ -453,7 +454,7 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool { log.Trace("SyncMirrors [repo: %-v]: no branches updated", m.Repo) } else { log.Trace("SyncMirrors [repo: %-v]: %d branches updated", m.Repo, len(results)) - gitRepo, err = repo_module.OpenRepository(ctx, m.Repo) + gitRepo, err = gitrepo.OpenRepository(ctx, m.Repo) if err != nil { log.Error("SyncMirrors [repo: %-v]: unable to OpenRepository: %v", m.Repo, err) return false diff --git a/services/mirror/mirror_push.go b/services/mirror/mirror_push.go index af968b0973483..35638d1a2a2e0 100644 --- a/services/mirror/mirror_push.go +++ b/services/mirror/mirror_push.go @@ -15,11 +15,11 @@ import ( "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/repository" - repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" @@ -146,7 +146,7 @@ func runPushSync(ctx context.Context, m *repo_model.PushMirror) error { if setting.LFS.StartServer { log.Trace("SyncMirrors [repo: %-v]: syncing LFS objects...", m.Repo) - gitRepo, err := repo_module.OpenRepository(ctx, repo) + gitRepo, err := gitrepo.OpenRepository(ctx, repo) if err != nil { log.Error("OpenRepository: %v", err) return errors.New("Unexpected error") diff --git a/services/pull/check.go b/services/pull/check.go index 39498e5c31faf..dd6c3ed230141 100644 --- a/services/pull/check.go +++ b/services/pull/check.go @@ -20,11 +20,11 @@ import ( "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/queue" - repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/timeutil" asymkey_service "code.gitea.io/gitea/services/asymkey" notify_service "code.gitea.io/gitea/services/notify" @@ -216,7 +216,7 @@ func getMergeCommit(ctx context.Context, pr *issues_model.PullRequest) (*git.Com return nil, fmt.Errorf("GetFullCommitID(%s) in %s: %w", prHeadRef, pr.BaseRepo.FullName(), err) } - gitRepo, err := repo_module.OpenRepository(ctx, pr.BaseRepo) + gitRepo, err := gitrepo.OpenRepository(ctx, pr.BaseRepo) if err != nil { return nil, fmt.Errorf("%-v OpenRepository: %w", pr.BaseRepo, err) } diff --git a/services/pull/merge_rebase.go b/services/pull/merge_rebase.go index 6b2f0c4752233..ecf376220e2af 100644 --- a/services/pull/merge_rebase.go +++ b/services/pull/merge_rebase.go @@ -9,8 +9,8 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" - repo_module "code.gitea.io/gitea/modules/repository" ) // getRebaseAmendMessage composes the message to amend commits in rebase merge of a pull request. @@ -58,7 +58,7 @@ func doMergeRebaseFastForward(ctx *mergeContext) error { } // Original repo to read template from. - baseGitRepo, err := repo_module.OpenRepository(ctx, ctx.pr.BaseRepo) + baseGitRepo, err := gitrepo.OpenRepository(ctx, ctx.pr.BaseRepo) if err != nil { log.Error("Unable to get Git repo for rebase: %v", err) return err diff --git a/services/pull/pull.go b/services/pull/pull.go index 0791668b81b52..9efee317c6196 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -23,6 +23,7 @@ import ( "code.gitea.io/gitea/modules/container" gitea_context "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" @@ -62,7 +63,7 @@ func NewPullRequest(ctx context.Context, repo *repo_model.Repository, issue *iss assigneeCommentMap := make(map[int64]*issues_model.Comment) // add first push codes comment - baseGitRepo, err := repo_module.OpenRepository(ctx, pr.BaseRepo) + baseGitRepo, err := gitrepo.OpenRepository(ctx, pr.BaseRepo) if err != nil { return err } @@ -269,7 +270,7 @@ func checkForInvalidation(ctx context.Context, requests issues_model.PullRequest if err != nil { return fmt.Errorf("GetRepositoryByIDCtx: %w", err) } - gitRepo, err := repo_module.OpenRepository(ctx, repo) + gitRepo, err := gitrepo.OpenRepository(ctx, repo) if err != nil { return fmt.Errorf("git.OpenRepository: %w", err) } @@ -845,7 +846,7 @@ func GetIssuesAllCommitStatus(ctx context.Context, issues issues_model.IssueList } gitRepo, ok := gitRepos[issue.RepoID] if !ok { - gitRepo, err = repo_module.OpenRepository(ctx, issue.Repo) + gitRepo, err = gitrepo.OpenRepository(ctx, issue.Repo) if err != nil { log.Error("Cannot open git repository %-v for issue #%d[%d]. Error: %v", issue.Repo, issue.Index, issue.ID, err) continue diff --git a/services/pull/pull_test.go b/services/pull/pull_test.go index 4b9314e410099..787910bf760f3 100644 --- a/services/pull/pull_test.go +++ b/services/pull/pull_test.go @@ -13,7 +13,7 @@ import ( "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/git" - repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/gitrepo" "github.com/stretchr/testify/assert" ) @@ -42,7 +42,7 @@ func TestPullRequest_GetDefaultMergeMessage_InternalTracker(t *testing.T) { pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) - gitRepo, err := repo_module.OpenRepository(git.DefaultContext, pr.BaseRepo) + gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, pr.BaseRepo) assert.NoError(t, err) defer gitRepo.Close() @@ -72,7 +72,7 @@ func TestPullRequest_GetDefaultMergeMessage_ExternalTracker(t *testing.T) { pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2, BaseRepo: baseRepo}) assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext)) - gitRepo, err := repo_module.OpenRepository(git.DefaultContext, pr.BaseRepo) + gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, pr.BaseRepo) assert.NoError(t, err) defer gitRepo.Close() diff --git a/services/release/release_test.go b/services/release/release_test.go index b1bd0fad3d643..3d0681f1e1710 100644 --- a/services/release/release_test.go +++ b/services/release/release_test.go @@ -13,7 +13,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" - repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/services/attachment" _ "code.gitea.io/gitea/models/actions" @@ -31,7 +31,7 @@ func TestRelease_Create(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - gitRepo, err := repo_module.OpenRepository(git.DefaultContext, repo) + gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo) assert.NoError(t, err) defer gitRepo.Close() @@ -136,7 +136,7 @@ func TestRelease_Update(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - gitRepo, err := repo_module.OpenRepository(git.DefaultContext, repo) + gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo) assert.NoError(t, err) defer gitRepo.Close() @@ -278,7 +278,7 @@ func TestRelease_createTag(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - gitRepo, err := repo_module.OpenRepository(git.DefaultContext, repo) + gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo) assert.NoError(t, err) defer gitRepo.Close() diff --git a/services/repository/adopt.go b/services/repository/adopt.go index fcad2cc61730c..bfb965063f33e 100644 --- a/services/repository/adopt.go +++ b/services/repository/adopt.go @@ -17,6 +17,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" @@ -126,7 +127,7 @@ func adoptRepository(ctx context.Context, repoPath string, u *user_model.User, r repo.IsEmpty = false // Don't bother looking this repo in the context it won't be there - gitRepo, err := repo_module.OpenRepository(ctx, repo) + gitRepo, err := gitrepo.OpenRepository(ctx, repo) if err != nil { return fmt.Errorf("openRepository: %w", err) } diff --git a/services/repository/archiver/archiver.go b/services/repository/archiver/archiver.go index 0dce167609023..01c58f0ce402a 100644 --- a/services/repository/archiver/archiver.go +++ b/services/repository/archiver/archiver.go @@ -15,11 +15,11 @@ import ( "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/queue" - repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/storage" ) @@ -210,7 +210,7 @@ func doArchive(ctx context.Context, r *ArchiveRequest) (*repo_model.RepoArchiver return nil, fmt.Errorf("archiver.LoadRepo failed: %w", err) } - gitRepo, err := repo_module.OpenRepository(ctx, repo) + gitRepo, err := gitrepo.OpenRepository(ctx, repo) if err != nil { return nil, err } diff --git a/services/repository/branch.go b/services/repository/branch.go index 7d4e23e14291c..63257c17604a9 100644 --- a/services/repository/branch.go +++ b/services/repository/branch.go @@ -17,6 +17,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/queue" @@ -160,7 +161,7 @@ func loadOneBranch(ctx context.Context, repo *repo_model.Repository, dbBranch *g if pr.HasMerged { baseGitRepo, ok := repoIDToGitRepo[pr.BaseRepoID] if !ok { - baseGitRepo, err = repo_module.OpenRepository(ctx, pr.BaseRepo) + baseGitRepo, err = gitrepo.OpenRepository(ctx, pr.BaseRepo) if err != nil { return nil, fmt.Errorf("OpenRepository: %v", err) } diff --git a/services/repository/create.go b/services/repository/create.go index 3f58518188705..a648c0d816787 100644 --- a/services/repository/create.go +++ b/services/repository/create.go @@ -16,6 +16,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/options" repo_module "code.gitea.io/gitea/modules/repository" @@ -175,7 +176,7 @@ func initRepository(ctx context.Context, repoPath string, u *user_model.User, re if len(opts.DefaultBranch) > 0 { repo.DefaultBranch = opts.DefaultBranch - gitRepo, err := repo_module.OpenRepository(ctx, repo) + gitRepo, err := gitrepo.OpenRepository(ctx, repo) if err != nil { return fmt.Errorf("openRepository: %w", err) } diff --git a/services/repository/files/content_test.go b/services/repository/files/content_test.go index 1958b875a4710..d50847789ace1 100644 --- a/services/repository/files/content_test.go +++ b/services/repository/files/content_test.go @@ -8,8 +8,8 @@ import ( "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/contexttest" + "code.gitea.io/gitea/modules/gitrepo" api "code.gitea.io/gitea/modules/structs" - repo_module "code.gitea.io/gitea/modules/repository" _ "code.gitea.io/gitea/models/actions" @@ -234,7 +234,7 @@ func TestGetBlobBySHA(t *testing.T) { ctx.SetParams(":id", "1") ctx.SetParams(":sha", sha) - gitRepo, err := repo_module.OpenRepository(ctx, ctx.Repo.Repository) + gitRepo, err := gitrepo.OpenRepository(ctx, ctx.Repo.Repository) if err != nil { t.Fail() } diff --git a/services/repository/files/file_test.go b/services/repository/files/file_test.go index a4d0dfa288409..675ddbddb3e8e 100644 --- a/services/repository/files/file_test.go +++ b/services/repository/files/file_test.go @@ -8,7 +8,7 @@ import ( "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/contexttest" - repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" @@ -109,7 +109,7 @@ func TestGetFileResponseFromCommit(t *testing.T) { repo := ctx.Repo.Repository branch := repo.DefaultBranch treePath := "README.md" - gitRepo, _ := repo_module.OpenRepository(ctx, repo) + gitRepo, _ := gitrepo.OpenRepository(ctx, repo) defer gitRepo.Close() commit, _ := gitRepo.GetBranchCommit(branch) expectedFileResponse := getExpectedFileResponse() diff --git a/services/repository/fork.go b/services/repository/fork.go index 37460c12105db..f9c13a109eba7 100644 --- a/services/repository/fork.go +++ b/services/repository/fork.go @@ -14,6 +14,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/structs" @@ -167,7 +168,7 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork return fmt.Errorf("createDelegateHooks: %w", err) } - gitRepo, err := repo_module.OpenRepository(txCtx, repo) + gitRepo, err := gitrepo.OpenRepository(txCtx, repo) if err != nil { return fmt.Errorf("OpenRepository: %w", err) } @@ -190,7 +191,7 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork log.Error("Copy language stat from oldRepo failed: %v", err) } - gitRepo, err := repo_module.OpenRepository(ctx, repo) + gitRepo, err := gitrepo.OpenRepository(ctx, repo) if err != nil { log.Error("Open created git repository failed: %v", err) } else { diff --git a/services/repository/hooks.go b/services/repository/hooks.go index 774d932c93514..97e9e290a3e3d 100644 --- a/services/repository/hooks.go +++ b/services/repository/hooks.go @@ -10,6 +10,7 @@ import ( "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/webhook" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" @@ -51,13 +52,13 @@ func SyncRepositoryHooks(ctx context.Context) error { // GenerateGitHooks generates git hooks from a template repository func GenerateGitHooks(ctx context.Context, templateRepo, generateRepo *repo_model.Repository) error { - generateGitRepo, err := repo_module.OpenRepository(ctx, generateRepo) + generateGitRepo, err := gitrepo.OpenRepository(ctx, generateRepo) if err != nil { return err } defer generateGitRepo.Close() - templateGitRepo, err := repo_module.OpenRepository(ctx, templateRepo) + templateGitRepo, err := gitrepo.OpenRepository(ctx, templateRepo) if err != nil { return err } diff --git a/services/repository/lfs.go b/services/repository/lfs.go index ee89c5dc2ce36..4504f796bd2f0 100644 --- a/services/repository/lfs.go +++ b/services/repository/lfs.go @@ -12,9 +12,9 @@ import ( git_model "code.gitea.io/gitea/models/git" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" - repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" ) @@ -70,7 +70,7 @@ func GarbageCollectLFSMetaObjectsForRepo(ctx context.Context, repo *repo_model.R } }() - gitRepo, err := repo_module.OpenRepository(ctx, repo) + gitRepo, err := gitrepo.OpenRepository(ctx, repo) if err != nil { log.Error("Unable to open git repository %-v: %v", repo, err) return err diff --git a/services/repository/push.go b/services/repository/push.go index e8a01da426c40..bedcf6f2524b5 100644 --- a/services/repository/push.go +++ b/services/repository/push.go @@ -16,6 +16,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" @@ -86,7 +87,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error { return fmt.Errorf("GetRepositoryByOwnerAndName failed: %w", err) } - gitRepo, err := repo_module.OpenRepository(ctx, repo) + gitRepo, err := gitrepo.OpenRepository(ctx, repo) if err != nil { return fmt.Errorf("OpenRepository[%s]: %w", repo.FullName(), err) } diff --git a/services/wiki/wiki_test.go b/services/wiki/wiki_test.go index 8091303909e0b..59c77060f2c27 100644 --- a/services/wiki/wiki_test.go +++ b/services/wiki/wiki_test.go @@ -12,7 +12,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" - repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/gitrepo" _ "code.gitea.io/gitea/models/actions" @@ -165,7 +165,7 @@ func TestRepository_AddWikiPage(t *testing.T) { webPath := UserTitleToWebPath("", userTitle) assert.NoError(t, AddWikiPage(git.DefaultContext, doer, repo, webPath, wikiContent, commitMsg)) // Now need to show that the page has been added: - gitRepo, err := repo_module.OpenWikiRepository(git.DefaultContext, repo) + gitRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo) if !assert.NoError(t, err) { return } @@ -213,7 +213,7 @@ func TestRepository_EditWikiPage(t *testing.T) { assert.NoError(t, EditWikiPage(git.DefaultContext, doer, repo, "Home", webPath, newWikiContent, commitMsg)) // Now need to show that the page has been added: - gitRepo, err := repo_module.OpenWikiRepository(git.DefaultContext, repo) + gitRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo) assert.NoError(t, err) masterTree, err := gitRepo.GetTree(DefaultBranch) assert.NoError(t, err) @@ -237,7 +237,7 @@ func TestRepository_DeleteWikiPage(t *testing.T) { assert.NoError(t, DeleteWikiPage(git.DefaultContext, doer, repo, "Home")) // Now need to show that the page has been added: - gitRepo, err := repo_module.OpenWikiRepository(git.DefaultContext, repo) + gitRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo) if !assert.NoError(t, err) { return } @@ -252,7 +252,7 @@ func TestRepository_DeleteWikiPage(t *testing.T) { func TestPrepareWikiFileName(t *testing.T) { unittest.PrepareTestEnv(t) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - gitRepo, err := repo_module.OpenWikiRepository(git.DefaultContext, repo) + gitRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo) if !assert.NoError(t, err) { return } diff --git a/tests/integration/api_packages_cargo_test.go b/tests/integration/api_packages_cargo_test.go index 0e3204fbf059a..c0705e0de5cf4 100644 --- a/tests/integration/api_packages_cargo_test.go +++ b/tests/integration/api_packages_cargo_test.go @@ -18,9 +18,9 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/json" cargo_module "code.gitea.io/gitea/modules/packages/cargo" - repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" cargo_router "code.gitea.io/gitea/routers/api/packages/cargo" cargo_service "code.gitea.io/gitea/services/packages/cargo" @@ -78,7 +78,7 @@ func testPackageCargo(t *testing.T, _ *neturl.URL) { assert.NoError(t, err) readGitContent := func(t *testing.T, path string) string { - gitRepo, err := repo_module.OpenRepository(db.DefaultContext, repo) + gitRepo, err := gitrepo.OpenRepository(db.DefaultContext, repo) assert.NoError(t, err) defer gitRepo.Close() diff --git a/tests/integration/api_releases_test.go b/tests/integration/api_releases_test.go index 1bfdd529f0bdd..5b1ab76ce97b3 100644 --- a/tests/integration/api_releases_test.go +++ b/tests/integration/api_releases_test.go @@ -18,7 +18,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" - repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/gitrepo" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/tests" @@ -110,7 +110,7 @@ func TestAPICreateAndUpdateRelease(t *testing.T) { session := loginUser(t, owner.LowerName) token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) - gitRepo, err := repo_module.OpenRepository(git.DefaultContext, repo) + gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo) assert.NoError(t, err) defer gitRepo.Close() @@ -173,7 +173,7 @@ func TestAPICreateReleaseToDefaultBranchOnExistingTag(t *testing.T) { session := loginUser(t, owner.LowerName) token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) - gitRepo, err := repo_module.OpenRepository(git.DefaultContext, repo) + gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo) assert.NoError(t, err) defer gitRepo.Close() diff --git a/tests/integration/api_repo_file_create_test.go b/tests/integration/api_repo_file_create_test.go index ace7452f1006f..0d192a1fe84ac 100644 --- a/tests/integration/api_repo_file_create_test.go +++ b/tests/integration/api_repo_file_create_test.go @@ -18,7 +18,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" @@ -167,7 +167,7 @@ func TestAPICreateFile(t *testing.T) { req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user2.Name, repo1.Name, treePath), &createFileOptions). AddTokenAuth(token2) resp := MakeRequest(t, req, http.StatusCreated) - gitRepo, _ := repo_module.OpenRepository(stdCtx.Background(), repo1) + gitRepo, _ := gitrepo.OpenRepository(stdCtx.Background(), repo1) commitID, _ := gitRepo.GetBranchCommitID(createFileOptions.NewBranchName) latestCommit, _ := gitRepo.GetCommitByPath(treePath) expectedFileResponse := getExpectedFileResponseForCreate("user2/repo1", commitID, treePath, latestCommit.ID.String()) @@ -285,7 +285,7 @@ func TestAPICreateFile(t *testing.T) { AddTokenAuth(token2) resp = MakeRequest(t, req, http.StatusCreated) emptyRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{OwnerName: "user2", Name: "empty-repo"}) // public repo - gitRepo, _ := repo_module.OpenRepository(stdCtx.Background(), emptyRepo) + gitRepo, _ := gitrepo.OpenRepository(stdCtx.Background(), emptyRepo) commitID, _ := gitRepo.GetBranchCommitID(createFileOptions.NewBranchName) latestCommit, _ := gitRepo.GetCommitByPath(treePath) expectedFileResponse := getExpectedFileResponseForCreate("user2/empty-repo", commitID, treePath, latestCommit.ID.String()) diff --git a/tests/integration/api_repo_file_update_test.go b/tests/integration/api_repo_file_update_test.go index 28af8370cd56d..195a1090c7c03 100644 --- a/tests/integration/api_repo_file_update_test.go +++ b/tests/integration/api_repo_file_update_test.go @@ -17,7 +17,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" @@ -135,7 +135,7 @@ func TestAPIUpdateFile(t *testing.T) { req := NewRequestWithJSON(t, "PUT", fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", user2.Name, repo1.Name, treePath), &updateFileOptions). AddTokenAuth(token2) resp := MakeRequest(t, req, http.StatusOK) - gitRepo, _ := repo_module.OpenRepository(stdCtx.Background(), repo1) + gitRepo, _ := gitrepo.OpenRepository(stdCtx.Background(), repo1) commitID, _ := gitRepo.GetBranchCommitID(updateFileOptions.NewBranchName) lasCommit, _ := gitRepo.GetCommitByPath(treePath) expectedFileResponse := getExpectedFileResponseForUpdate(commitID, treePath, lasCommit.ID.String()) diff --git a/tests/integration/api_repo_files_change_test.go b/tests/integration/api_repo_files_change_test.go index b829512d0425c..ab5cf19a9c88d 100644 --- a/tests/integration/api_repo_files_change_test.go +++ b/tests/integration/api_repo_files_change_test.go @@ -16,7 +16,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" @@ -96,7 +96,7 @@ func TestAPIChangeFiles(t *testing.T) { req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/contents", user2.Name, repo1.Name), &changeFilesOptions). AddTokenAuth(token2) resp := MakeRequest(t, req, http.StatusCreated) - gitRepo, _ := repo_module.OpenRepository(stdCtx.Background(), repo1) + gitRepo, _ := gitrepo.OpenRepository(stdCtx.Background(), repo1) commitID, _ := gitRepo.GetBranchCommitID(changeFilesOptions.NewBranchName) createLasCommit, _ := gitRepo.GetCommitByPath(createTreePath) updateLastCommit, _ := gitRepo.GetCommitByPath(updateTreePath) diff --git a/tests/integration/api_repo_get_contents_list_test.go b/tests/integration/api_repo_get_contents_list_test.go index 8c9dfca38be83..1ba74490a30da 100644 --- a/tests/integration/api_repo_get_contents_list_test.go +++ b/tests/integration/api_repo_get_contents_list_test.go @@ -14,7 +14,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" - repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" repo_service "code.gitea.io/gitea/services/repository" @@ -72,7 +72,7 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) { token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository) // Get the commit ID of the default branch - gitRepo, err := repo_module.OpenRepository(git.DefaultContext, repo1) + gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo1) assert.NoError(t, err) defer gitRepo.Close() diff --git a/tests/integration/api_repo_get_contents_test.go b/tests/integration/api_repo_get_contents_test.go index 6f6c65c226298..68a8608117208 100644 --- a/tests/integration/api_repo_get_contents_test.go +++ b/tests/integration/api_repo_get_contents_test.go @@ -14,7 +14,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" - repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" repo_service "code.gitea.io/gitea/services/repository" @@ -74,7 +74,7 @@ func testAPIGetContents(t *testing.T, u *url.URL) { token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository) // Get the commit ID of the default branch - gitRepo, err := repo_module.OpenRepository(git.DefaultContext, repo1) + gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo1) assert.NoError(t, err) defer gitRepo.Close() diff --git a/tests/integration/api_repo_git_tags_test.go b/tests/integration/api_repo_git_tags_test.go index 17ab27bc73c5f..937f6a829c2cc 100644 --- a/tests/integration/api_repo_git_tags_test.go +++ b/tests/integration/api_repo_git_tags_test.go @@ -13,7 +13,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" - repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/gitrepo" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/tests" @@ -33,7 +33,7 @@ func TestAPIGitTags(t *testing.T) { _ = git.NewCommand(git.DefaultContext, "config", "user.name").AddDynamicArguments(user.Name).Run(&git.RunOpts{Dir: repo.RepoPath()}) _ = git.NewCommand(git.DefaultContext, "config", "user.email").AddDynamicArguments(user.Email).Run(&git.RunOpts{Dir: repo.RepoPath()}) - gitRepo, _ := repo_module.OpenRepository(git.DefaultContext, repo) + gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo) defer gitRepo.Close() commit, _ := gitRepo.GetBranchCommit("master") diff --git a/tests/integration/mirror_pull_test.go b/tests/integration/mirror_pull_test.go index fd5946f345005..2e71b80fbb5db 100644 --- a/tests/integration/mirror_pull_test.go +++ b/tests/integration/mirror_pull_test.go @@ -12,9 +12,9 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/migration" "code.gitea.io/gitea/modules/repository" - repo_module "code.gitea.io/gitea/modules/repository" mirror_service "code.gitea.io/gitea/services/mirror" release_service "code.gitea.io/gitea/services/release" repo_service "code.gitea.io/gitea/services/repository" @@ -55,7 +55,7 @@ func TestMirrorPull(t *testing.T) { mirror, err := repository.MigrateRepositoryGitData(ctx, user, mirrorRepo, opts, nil) assert.NoError(t, err) - gitRepo, err := repo_module.OpenRepository(git.DefaultContext, repo) + gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo) assert.NoError(t, err) defer gitRepo.Close() diff --git a/tests/integration/mirror_push_test.go b/tests/integration/mirror_push_test.go index aa775d17e2f41..3dc719593c306 100644 --- a/tests/integration/mirror_push_test.go +++ b/tests/integration/mirror_push_test.go @@ -17,7 +17,7 @@ import ( user_model "code.gitea.io/gitea/models/user" gitea_context "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" - repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/services/migrations" mirror_service "code.gitea.io/gitea/services/mirror" @@ -56,14 +56,14 @@ func testMirrorPush(t *testing.T, u *url.URL) { ok := mirror_service.SyncPushMirror(context.Background(), mirrors[0].ID) assert.True(t, ok) - srcGitRepo, err := repo_module.OpenRepository(git.DefaultContext, srcRepo) + srcGitRepo, err := gitrepo.OpenRepository(git.DefaultContext, srcRepo) assert.NoError(t, err) defer srcGitRepo.Close() srcCommit, err := srcGitRepo.GetBranchCommit("master") assert.NoError(t, err) - mirrorGitRepo, err := repo_module.OpenRepository(git.DefaultContext, mirrorRepo) + mirrorGitRepo, err := gitrepo.OpenRepository(git.DefaultContext, mirrorRepo) assert.NoError(t, err) defer mirrorGitRepo.Close() diff --git a/tests/integration/repofiles_change_test.go b/tests/integration/repofiles_change_test.go index c4575d984f2ab..19fbd1754cc2f 100644 --- a/tests/integration/repofiles_change_test.go +++ b/tests/integration/repofiles_change_test.go @@ -14,7 +14,7 @@ import ( "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/contexttest" "code.gitea.io/gitea/modules/git" - repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" files_service "code.gitea.io/gitea/services/repository/files" @@ -263,7 +263,7 @@ func TestChangeRepoFilesForCreate(t *testing.T) { // asserts assert.NoError(t, err) - gitRepo, _ := repo_module.OpenRepository(git.DefaultContext, repo) + gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo) defer gitRepo.Close() commitID, _ := gitRepo.GetBranchCommitID(opts.NewBranch) @@ -300,7 +300,7 @@ func TestChangeRepoFilesForUpdate(t *testing.T) { // asserts assert.NoError(t, err) - gitRepo, _ := repo_module.OpenRepository(git.DefaultContext, repo) + gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo) defer gitRepo.Close() commit, _ := gitRepo.GetBranchCommit(opts.NewBranch) @@ -336,7 +336,7 @@ func TestChangeRepoFilesForUpdateWithFileMove(t *testing.T) { // asserts assert.NoError(t, err) - gitRepo, _ := repo_module.OpenRepository(git.DefaultContext, repo) + gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo) defer gitRepo.Close() commit, _ := gitRepo.GetBranchCommit(opts.NewBranch) @@ -387,7 +387,7 @@ func TestChangeRepoFilesWithoutBranchNames(t *testing.T) { // asserts assert.NoError(t, err) - gitRepo, _ := repo_module.OpenRepository(git.DefaultContext, repo) + gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo) defer gitRepo.Close() commit, _ := gitRepo.GetBranchCommit(repo.DefaultBranch) From 158ad7167086eca50e822c2fbeea93a03fd65ef3 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 26 Jan 2024 13:13:25 +0800 Subject: [PATCH 03/18] revert unnecessary change --- models/issues/pull.go | 77 ++++++++++++++++++++++++++++++++++++++ services/issue/issue.go | 82 +---------------------------------------- services/pull/pull.go | 2 +- 3 files changed, 79 insertions(+), 82 deletions(-) diff --git a/models/issues/pull.go b/models/issues/pull.go index ce170130c4c47..2cb1e1b971e9c 100644 --- a/models/issues/pull.go +++ b/models/issues/pull.go @@ -19,6 +19,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" @@ -854,6 +855,82 @@ func MergeBlockedByOutdatedBranch(protectBranch *git_model.ProtectedBranch, pr * return protectBranch.BlockOnOutdatedBranch && pr.CommitsBehind > 0 } +func PullRequestCodeOwnersReview(ctx context.Context, pull *Issue, pr *PullRequest) error { + files := []string{"CODEOWNERS", "docs/CODEOWNERS", ".gitea/CODEOWNERS"} + + if pr.IsWorkInProgress(ctx) { + return nil + } + + if err := pr.LoadBaseRepo(ctx); err != nil { + return err + } + + repo, err := gitrepo.OpenRepository(ctx, pr.BaseRepo) + if err != nil { + return err + } + defer repo.Close() + + branch, err := repo.GetDefaultBranch() + if err != nil { + return err + } + + commit, err := repo.GetBranchCommit(branch) + if err != nil { + return err + } + + var data string + for _, file := range files { + if blob, err := commit.GetBlobByPath(file); err == nil { + data, err = blob.GetBlobContent(setting.UI.MaxDisplayFileSize) + if err == nil { + break + } + } + } + + rules, _ := GetCodeOwnersFromContent(ctx, data) + changedFiles, err := repo.GetFilesChangedBetween(git.BranchPrefix+pr.BaseBranch, pr.GetGitRefName()) + if err != nil { + return err + } + + uniqUsers := make(map[int64]*user_model.User) + uniqTeams := make(map[string]*org_model.Team) + for _, rule := range rules { + for _, f := range changedFiles { + if (rule.Rule.MatchString(f) && !rule.Negative) || (!rule.Rule.MatchString(f) && rule.Negative) { + for _, u := range rule.Users { + uniqUsers[u.ID] = u + } + for _, t := range rule.Teams { + uniqTeams[fmt.Sprintf("%d/%d", t.OrgID, t.ID)] = t + } + } + } + } + + for _, u := range uniqUsers { + if u.ID != pull.Poster.ID { + if _, err := AddReviewRequest(ctx, pull, u, pull.Poster); err != nil { + log.Warn("Failed add assignee user: %s to PR review: %s#%d, error: %s", u.Name, pr.BaseRepo.Name, pr.ID, err) + return err + } + } + } + for _, t := range uniqTeams { + if _, err := AddTeamReviewRequest(ctx, pull, t, pull.Poster); err != nil { + log.Warn("Failed add assignee team: %s to PR review: %s#%d, error: %s", t.Name, pr.BaseRepo.Name, pr.ID, err) + return err + } + } + + return nil +} + // GetCodeOwnersFromContent returns the code owners configuration // Return empty slice if files missing // Return warning messages on parsing errors diff --git a/services/issue/issue.go b/services/issue/issue.go index 265f712e8f5aa..b1f418c32e565 100644 --- a/services/issue/issue.go +++ b/services/issue/issue.go @@ -10,16 +10,12 @@ import ( activities_model "code.gitea.io/gitea/models/activities" "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" - org_model "code.gitea.io/gitea/models/organization" access_model "code.gitea.io/gitea/models/perm/access" project_model "code.gitea.io/gitea/models/project" repo_model "code.gitea.io/gitea/models/repo" system_model "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/gitrepo" - "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/storage" notify_service "code.gitea.io/gitea/services/notify" ) @@ -52,82 +48,6 @@ func NewIssue(ctx context.Context, repo *repo_model.Repository, issue *issues_mo return nil } -func PullRequestCodeOwnersReview(ctx context.Context, pull *issues_model.Issue, pr *issues_model.PullRequest) error { - files := []string{"CODEOWNERS", "docs/CODEOWNERS", ".gitea/CODEOWNERS"} - - if pr.IsWorkInProgress(ctx) { - return nil - } - - if err := pr.LoadBaseRepo(ctx); err != nil { - return err - } - - repo, err := gitrepo.OpenRepository(ctx, pr.BaseRepo) - if err != nil { - return err - } - defer repo.Close() - - branch, err := repo.GetDefaultBranch() - if err != nil { - return err - } - - commit, err := repo.GetBranchCommit(branch) - if err != nil { - return err - } - - var data string - for _, file := range files { - if blob, err := commit.GetBlobByPath(file); err == nil { - data, err = blob.GetBlobContent(setting.UI.MaxDisplayFileSize) - if err == nil { - break - } - } - } - - rules, _ := issues_model.GetCodeOwnersFromContent(ctx, data) - changedFiles, err := repo.GetFilesChangedBetween(git.BranchPrefix+pr.BaseBranch, pr.GetGitRefName()) - if err != nil { - return err - } - - uniqUsers := make(map[int64]*user_model.User) - uniqTeams := make(map[string]*org_model.Team) - for _, rule := range rules { - for _, f := range changedFiles { - if (rule.Rule.MatchString(f) && !rule.Negative) || (!rule.Rule.MatchString(f) && rule.Negative) { - for _, u := range rule.Users { - uniqUsers[u.ID] = u - } - for _, t := range rule.Teams { - uniqTeams[fmt.Sprintf("%d/%d", t.OrgID, t.ID)] = t - } - } - } - } - - for _, u := range uniqUsers { - if u.ID != pull.Poster.ID { - if _, err := issues_model.AddReviewRequest(ctx, pull, u, pull.Poster); err != nil { - log.Warn("Failed add assignee user: %s to PR review: %s#%d, error: %s", u.Name, pr.BaseRepo.Name, pr.ID, err) - return err - } - } - } - for _, t := range uniqTeams { - if _, err := issues_model.AddTeamReviewRequest(ctx, pull, t, pull.Poster); err != nil { - log.Warn("Failed add assignee team: %s to PR review: %s#%d, error: %s", t.Name, pr.BaseRepo.Name, pr.ID, err) - return err - } - } - - return nil -} - // ChangeTitle changes the title of this issue, as the given user. func ChangeTitle(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, title string) error { oldTitle := issue.Title @@ -142,7 +62,7 @@ func ChangeTitle(ctx context.Context, issue *issues_model.Issue, doer *user_mode } if issue.IsPull && issues_model.HasWorkInProgressPrefix(oldTitle) && !issues_model.HasWorkInProgressPrefix(title) { - if err := PullRequestCodeOwnersReview(ctx, issue, issue.PullRequest); err != nil { + if err := issues_model.PullRequestCodeOwnersReview(ctx, issue, issue.PullRequest); err != nil { return err } } diff --git a/services/pull/pull.go b/services/pull/pull.go index 9efee317c6196..c849deed2e289 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -128,7 +128,7 @@ func NewPullRequest(ctx context.Context, repo *repo_model.Repository, issue *iss } if !pr.IsWorkInProgress(ctx) { - if err := issue_service.PullRequestCodeOwnersReview(ctx, issue, pr); err != nil { + if err := issues_model.PullRequestCodeOwnersReview(ctx, issue, pr); err != nil { return err } } From 3df7bdd2ce7e9045ebcb81b42581dad5d771f818 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 26 Jan 2024 13:44:52 +0800 Subject: [PATCH 04/18] More refactoring --- modules/repository/repo.go | 3 ++- services/asymkey/sign.go | 7 +++++-- services/wiki/wiki.go | 4 ++-- tests/integration/pull_merge_test.go | 5 +++-- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/modules/repository/repo.go b/modules/repository/repo.go index 5af69763d152e..20cc664b5b2d7 100644 --- a/modules/repository/repo.go +++ b/modules/repository/repo.go @@ -19,6 +19,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/migration" @@ -291,7 +292,7 @@ func SyncRepoTags(ctx context.Context, repoID int64) error { return err } - gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) + gitRepo, err := gitrepo.OpenRepository(ctx, repo) if err != nil { return err } diff --git a/services/asymkey/sign.go b/services/asymkey/sign.go index 0c4aac8156934..1a9da7e9ae915 100644 --- a/services/asymkey/sign.go +++ b/services/asymkey/sign.go @@ -13,8 +13,10 @@ import ( "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" + repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/setting" @@ -167,7 +169,8 @@ Loop: } // SignWikiCommit determines if we should sign the commits to this repository wiki -func SignWikiCommit(ctx context.Context, repoWikiPath string, u *user_model.User) (bool, string, *git.Signature, error) { +func SignWikiCommit(ctx context.Context, repo *repo_model.Repository, u *user_model.User) (bool, string, *git.Signature, error) { + repoWikiPath := repo.WikiPath() rules := signingModeFromStrings(setting.Repository.Signing.Wiki) signingKey, sig := SigningKey(ctx, repoWikiPath) if signingKey == "" { @@ -201,7 +204,7 @@ Loop: return false, "", nil, &ErrWontSign{twofa} } case parentSigned: - gitRepo, err := git.OpenRepository(ctx, repoWikiPath) + gitRepo, err := gitrepo.OpenRepository(ctx, repo) if err != nil { return false, "", nil, err } diff --git a/services/wiki/wiki.go b/services/wiki/wiki.go index ce54a00da73b4..50d52d3140fe8 100644 --- a/services/wiki/wiki.go +++ b/services/wiki/wiki.go @@ -191,7 +191,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model committer := doer.NewGitSig() - sign, signingKey, signer, _ := asymkey_service.SignWikiCommit(ctx, repo.WikiPath(), doer) + sign, signingKey, signer, _ := asymkey_service.SignWikiCommit(ctx, repo, doer) if sign { commitTreeOpts.KeyID = signingKey if repo.GetTrustModel() == repo_model.CommitterTrustModel || repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { @@ -314,7 +314,7 @@ func DeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model committer := doer.NewGitSig() - sign, signingKey, signer, _ := asymkey_service.SignWikiCommit(ctx, repo.WikiPath(), doer) + sign, signingKey, signer, _ := asymkey_service.SignWikiCommit(ctx, repo, doer) if sign { commitTreeOpts.KeyID = signingKey if repo.GetTrustModel() == repo_model.CommitterTrustModel || repo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel { diff --git a/tests/integration/pull_merge_test.go b/tests/integration/pull_merge_test.go index 2aa6742a56ac0..fcd7fecd52dd5 100644 --- a/tests/integration/pull_merge_test.go +++ b/tests/integration/pull_merge_test.go @@ -25,6 +25,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/modules/translation" @@ -255,7 +256,7 @@ func TestCantMergeConflict(t *testing.T) { BaseBranch: "base", }) - gitRepo, err := git.OpenRepository(git.DefaultContext, repo_model.RepoPath(user1.Name, repo1.Name)) + gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo1) assert.NoError(t, err) err = pull.Merge(context.Background(), pr, user1, gitRepo, repo_model.MergeStyleMerge, "", "CONFLICT", false) @@ -348,7 +349,7 @@ func TestCantMergeUnrelated(t *testing.T) { session.MakeRequest(t, req, http.StatusCreated) // Now this PR could be marked conflict - or at least a race may occur - so drop down to pure code at this point... - gitRepo, err := git.OpenRepository(git.DefaultContext, path) + gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo1) assert.NoError(t, err) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ HeadRepoID: repo1.ID, From 4eea9237386e9c2bdcf760ed5722f352f83c6ba1 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 26 Jan 2024 14:41:56 +0800 Subject: [PATCH 05/18] Fix typo --- services/asymkey/sign.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/asymkey/sign.go b/services/asymkey/sign.go index 1a9da7e9ae915..2f5d76a29334b 100644 --- a/services/asymkey/sign.go +++ b/services/asymkey/sign.go @@ -204,7 +204,7 @@ Loop: return false, "", nil, &ErrWontSign{twofa} } case parentSigned: - gitRepo, err := gitrepo.OpenRepository(ctx, repo) + gitRepo, err := gitrepo.OpenWikiRepository(ctx, repo) if err != nil { return false, "", nil, err } From 8309661f5245325e5551064a85dce446bca4d3db Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 26 Jan 2024 14:45:04 +0800 Subject: [PATCH 06/18] Fix bug --- services/mirror/mirror_push.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/services/mirror/mirror_push.go b/services/mirror/mirror_push.go index 35638d1a2a2e0..21ba0afeffd6e 100644 --- a/services/mirror/mirror_push.go +++ b/services/mirror/mirror_push.go @@ -146,7 +146,12 @@ func runPushSync(ctx context.Context, m *repo_model.PushMirror) error { if setting.LFS.StartServer { log.Trace("SyncMirrors [repo: %-v]: syncing LFS objects...", m.Repo) - gitRepo, err := gitrepo.OpenRepository(ctx, repo) + var gitRepo *git.Repository + if isWiki { + gitRepo, err = gitrepo.OpenWikiRepository(ctx, repo) + } else { + gitRepo, err = gitrepo.OpenRepository(ctx, repo) + } if err != nil { log.Error("OpenRepository: %v", err) return errors.New("Unexpected error") From 8e94d70403f26f96b49fa5ff0dbb0e46cd166480 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 26 Jan 2024 15:09:11 +0800 Subject: [PATCH 07/18] More refactoring --- models/activities/repo_activity.go | 5 +- models/issues/comment.go | 5 +- modules/context/api.go | 2 +- modules/context/context.go | 4 +- modules/git/repo_base.go | 44 ------------------ modules/git/repo_branch.go | 23 ---------- modules/gitrepo/branch.go | 33 ++++++++++++++ modules/gitrepo/gitrepo.go | 68 ++++++++++++++++++++++++++++ routers/api/v1/repo/pull.go | 2 +- routers/api/v1/repo/pull_review.go | 5 +- routers/api/v1/utils/git.go | 3 +- services/mirror/mirror_pull.go | 2 +- services/pull/comment.go | 5 +- services/pull/commit_status.go | 3 +- services/pull/merge_squash.go | 3 +- services/pull/patch.go | 3 +- services/pull/pull.go | 8 ++-- services/pull/review.go | 3 +- services/release/release.go | 3 +- services/repository/branch.go | 4 -- services/repository/files/commit.go | 3 +- services/repository/files/content.go | 5 +- services/repository/files/patch.go | 3 +- services/repository/files/update.go | 3 +- 24 files changed, 140 insertions(+), 102 deletions(-) create mode 100644 modules/gitrepo/branch.go diff --git a/models/activities/repo_activity.go b/models/activities/repo_activity.go index 91f5ac12bdc04..ba5e4959f0df8 100644 --- a/models/activities/repo_activity.go +++ b/models/activities/repo_activity.go @@ -14,6 +14,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "xorm.io/xorm" ) @@ -65,7 +66,7 @@ func GetActivityStats(ctx context.Context, repo *repo_model.Repository, timeFrom return nil, fmt.Errorf("FillUnresolvedIssues: %w", err) } if code { - gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.RepoPath()) + gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo) if err != nil { return nil, fmt.Errorf("OpenRepository: %w", err) } @@ -82,7 +83,7 @@ func GetActivityStats(ctx context.Context, repo *repo_model.Repository, timeFrom // GetActivityStatsTopAuthors returns top author stats for git commits for all branches func GetActivityStatsTopAuthors(ctx context.Context, repo *repo_model.Repository, timeFrom time.Time, count int) ([]*ActivityAuthorData, error) { - gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.RepoPath()) + gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo) if err != nil { return nil, fmt.Errorf("OpenRepository: %w", err) } diff --git a/models/issues/comment.go b/models/issues/comment.go index 8a3bae5b883d2..c63fcab8944f5 100644 --- a/models/issues/comment.go +++ b/models/issues/comment.go @@ -18,7 +18,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/container" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/references" @@ -762,8 +762,7 @@ func (c *Comment) LoadPushCommits(ctx context.Context) (err error) { c.OldCommit = data.CommitIDs[0] c.NewCommit = data.CommitIDs[1] } else { - repoPath := c.Issue.Repo.RepoPath() - gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repoPath) + gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, c.Issue.Repo) if err != nil { return err } diff --git a/modules/context/api.go b/modules/context/api.go index 3ac70d4857d79..e226264a87352 100644 --- a/modules/context/api.go +++ b/modules/context/api.go @@ -224,7 +224,7 @@ func APIContexter() func(http.Handler) http.Handler { defer baseCleanUp() ctx.Base.AppendContextValue(apiContextKey, ctx) - ctx.Base.AppendContextValueFunc(git.RepositoryContextKey, func() any { return ctx.Repo.GitRepo }) + ctx.Base.AppendContextValueFunc(gitrepo.RepositoryContextKey, func() any { return ctx.Repo.GitRepo }) // If request sends files, parse them here otherwise the Query() can't be parsed and the CsrfToken will be invalid. if ctx.Req.Method == "POST" && strings.Contains(ctx.Req.Header.Get("Content-Type"), "multipart/form-data") { diff --git a/modules/context/context.go b/modules/context/context.go index 8a94e958b5169..d19c5d119830d 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -17,7 +17,7 @@ import ( "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" mc "code.gitea.io/gitea/modules/cache" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/httpcache" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/templates" @@ -163,7 +163,7 @@ func Contexter() func(next http.Handler) http.Handler { ctx.Data["PageData"] = ctx.PageData ctx.Base.AppendContextValue(WebContextKey, ctx) - ctx.Base.AppendContextValueFunc(git.RepositoryContextKey, func() any { return ctx.Repo.GitRepo }) + ctx.Base.AppendContextValueFunc(gitrepo.RepositoryContextKey, func() any { return ctx.Repo.GitRepo }) ctx.Csrf = PrepareCSRFProtector(csrfOpts, ctx) diff --git a/modules/git/repo_base.go b/modules/git/repo_base.go index a9d91d2deb2d2..6c148d9af516a 100644 --- a/modules/git/repo_base.go +++ b/modules/git/repo_base.go @@ -3,48 +3,4 @@ package git -import ( - "context" - "io" -) - var isGogit bool - -// contextKey is a value for use with context.WithValue. -type contextKey struct { - name string -} - -// RepositoryContextKey is a context key. It is used with context.Value() to get the current Repository for the context -var RepositoryContextKey = &contextKey{"repository"} - -// RepositoryFromContext attempts to get the repository from the context -func RepositoryFromContext(ctx context.Context, path string) *Repository { - value := ctx.Value(RepositoryContextKey) - if value == nil { - return nil - } - - if repo, ok := value.(*Repository); ok && repo != nil { - if repo.Path == path { - return repo - } - } - - return nil -} - -type nopCloser func() - -func (nopCloser) Close() error { return nil } - -// RepositoryFromContextOrOpen attempts to get the repository from the context or just opens it -func RepositoryFromContextOrOpen(ctx context.Context, path string) (*Repository, io.Closer, error) { - gitRepo := RepositoryFromContext(ctx, path) - if gitRepo != nil { - return gitRepo, nopCloser(nil), nil - } - - gitRepo, err := OpenRepository(ctx, path) - return gitRepo, gitRepo, err -} diff --git a/modules/git/repo_branch.go b/modules/git/repo_branch.go index 59580939757c1..979c5dec9175a 100644 --- a/modules/git/repo_branch.go +++ b/modules/git/repo_branch.go @@ -86,29 +86,6 @@ func (repo *Repository) GetBranch(branch string) (*Branch, error) { }, nil } -// GetBranchesByPath returns a branch by it's path -// if limit = 0 it will not limit -func GetBranchesByPath(ctx context.Context, path string, skip, limit int) ([]*Branch, int, error) { - gitRepo, err := OpenRepository(ctx, path) - if err != nil { - return nil, 0, err - } - defer gitRepo.Close() - - return gitRepo.GetBranches(skip, limit) -} - -// GetBranchCommitID returns a branch commit ID by its name -func GetBranchCommitID(ctx context.Context, path, branch string) (string, error) { - gitRepo, err := OpenRepository(ctx, path) - if err != nil { - return "", err - } - defer gitRepo.Close() - - return gitRepo.GetBranchCommitID(branch) -} - // GetBranches returns a slice of *git.Branch func (repo *Repository) GetBranches(skip, limit int) ([]*Branch, int, error) { brs, countAll, err := repo.GetBranchNames(skip, limit) diff --git a/modules/gitrepo/branch.go b/modules/gitrepo/branch.go new file mode 100644 index 0000000000000..8f22181b64a7a --- /dev/null +++ b/modules/gitrepo/branch.go @@ -0,0 +1,33 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package gitrepo + +import ( + "context" + + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/modules/git" +) + +// GetBranchesByPath returns a branch by it's path +// if limit = 0 it will not limit +func GetBranchesByPath(ctx context.Context, repo *repo_model.Repository, skip, limit int) ([]*git.Branch, int, error) { + gitRepo, err := OpenRepository(ctx, repo) + if err != nil { + return nil, 0, err + } + defer gitRepo.Close() + + return gitRepo.GetBranches(skip, limit) +} + +func GetBranchCommitID(ctx context.Context, repo *repo_model.Repository, branch string) (string, error) { + gitRepo, err := OpenRepository(ctx, repo) + if err != nil { + return "", err + } + defer gitRepo.Close() + + return gitRepo.GetBranchCommitID(branch) +} diff --git a/modules/gitrepo/gitrepo.go b/modules/gitrepo/gitrepo.go index 2af4cda60d9bf..7fcc4495a7a66 100644 --- a/modules/gitrepo/gitrepo.go +++ b/modules/gitrepo/gitrepo.go @@ -6,6 +6,7 @@ package gitrepo import ( "context" "fmt" + "io" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" @@ -30,3 +31,70 @@ func DeleteRepository(ctx context.Context, repo *repo_model.Repository) error { } return nil } + +// contextKey is a value for use with context.WithValue. +type contextKey struct { + name string +} + +// RepositoryContextKey is a context key. It is used with context.Value() to get the current Repository for the context +var RepositoryContextKey = &contextKey{"repository"} + +// RepositoryFromContext attempts to get the repository from the context +func RepositoryFromContext(ctx context.Context, repo *repo_model.Repository) *Repository { + value := ctx.Value(RepositoryContextKey) + if value == nil { + return nil + } + + if gitRepo, ok := value.(*Repository); ok && gitRepo != nil { + if gitRepo.Path == repo.RepoPath() { + return gitRepo + } + } + + return nil +} + +type nopCloser func() + +func (nopCloser) Close() error { return nil } + +// RepositoryFromContextOrOpen attempts to get the repository from the context or just opens it +func RepositoryFromContextOrOpen(ctx context.Context, repo *repo_model.Repository) (*Repository, io.Closer, error) { + gitRepo := RepositoryFromContext(ctx, repo) + if gitRepo != nil { + return gitRepo, nopCloser(nil), nil + } + + gitRepo, err := OpenRepository(ctx, repo) + return gitRepo, gitRepo, err +} + +// RepositoryFromContext attempts to get the repository from the context +func repositoryFromContext(ctx context.Context, path string) *git.Repository { + value := ctx.Value(RepositoryContextKey) + if value == nil { + return nil + } + + if repo, ok := value.(*git.Repository); ok && repo != nil { + if repo.Path == path { + return repo + } + } + + return nil +} + +// RepositoryFromContextOrOpenPath attempts to get the repository from the context or just opens it +// Deprecated: Use RepositoryFromContextOrOpen instead +func RepositoryFromContextOrOpenPath(ctx context.Context, path string) (*git.Repository, io.Closer, error) { + gitRepo := repositoryFromContext(ctx, path) + if gitRepo != nil { + return gitRepo, nopCloser(nil), nil + } + + gitRepo, err := git.OpenRepository(ctx, path) + return gitRepo, gitRepo, err +} diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index 7647c88f2a082..eaf406e64d8a6 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -1309,7 +1309,7 @@ func GetPullRequestCommits(ctx *context.APIContext) { } var prInfo *git.CompareInfo - baseGitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, pr.BaseRepo.RepoPath()) + baseGitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, pr.BaseRepo) if err != nil { ctx.ServerError("OpenRepository", err) return diff --git a/routers/api/v1/repo/pull_review.go b/routers/api/v1/repo/pull_review.go index 7b9445be4c068..07d8f4877bb3d 100644 --- a/routers/api/v1/repo/pull_review.go +++ b/routers/api/v1/repo/pull_review.go @@ -13,7 +13,7 @@ import ( access_model "code.gitea.io/gitea/models/perm/access" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/api/v1/utils" @@ -329,8 +329,7 @@ func CreatePullReview(ctx *context.APIContext) { // if CommitID is empty, set it as lastCommitID if opts.CommitID == "" { - - gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, pr.Issue.Repo.RepoPath()) + gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, pr.Issue.Repo) if err != nil { ctx.Error(http.StatusInternalServerError, "git.OpenRepository", err) return diff --git a/routers/api/v1/utils/git.go b/routers/api/v1/utils/git.go index 39714e343f013..2299cdc247548 100644 --- a/routers/api/v1/utils/git.go +++ b/routers/api/v1/utils/git.go @@ -10,6 +10,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" ) @@ -79,7 +80,7 @@ func ConvertToObjectID(ctx gocontext.Context, repo *context.Repository, commitID } } - gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.Repository.RepoPath()) + gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo.Repository) if err != nil { return objectFormat.EmptyObjectID(), fmt.Errorf("RepositoryFromContextOrOpen: %w", err) } diff --git a/services/mirror/mirror_pull.go b/services/mirror/mirror_pull.go index b2635c5b98518..3418cf90dfe38 100644 --- a/services/mirror/mirror_pull.go +++ b/services/mirror/mirror_pull.go @@ -397,7 +397,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo } log.Trace("SyncMirrors [repo: %-v]: invalidating mirror branch caches...", m.Repo) - branches, _, err := git.GetBranchesByPath(ctx, m.Repo.RepoPath(), 0, 0) + branches, _, err := gitrepo.GetBranchesByPath(ctx, m.Repo, 0, 0) if err != nil { log.Error("SyncMirrors [repo: %-v]: failed to GetBranches: %v", m.Repo, err) return nil, false diff --git a/services/pull/comment.go b/services/pull/comment.go index 14fba52f1e7e3..d538b118d5bf7 100644 --- a/services/pull/comment.go +++ b/services/pull/comment.go @@ -9,7 +9,7 @@ import ( issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/json" ) @@ -17,8 +17,7 @@ import ( // isForcePush will be true if oldCommit isn't on the branch // Commit on baseBranch will skip func getCommitIDsFromRepo(ctx context.Context, repo *repo_model.Repository, oldCommitID, newCommitID, baseBranch string) (commitIDs []string, isForcePush bool, err error) { - repoPath := repo.RepoPath() - gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repoPath) + gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo) if err != nil { return nil, false, err } diff --git a/services/pull/commit_status.go b/services/pull/commit_status.go index 39d60380ff202..b73816c7eb225 100644 --- a/services/pull/commit_status.go +++ b/services/pull/commit_status.go @@ -11,6 +11,7 @@ import ( git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/structs" @@ -116,7 +117,7 @@ func GetPullRequestCommitStatusState(ctx context.Context, pr *issues_model.PullR } // check if all required status checks are successful - headGitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, pr.HeadRepo.RepoPath()) + headGitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, pr.HeadRepo) if err != nil { return "", errors.Wrap(err, "OpenRepository") } diff --git a/services/pull/merge_squash.go b/services/pull/merge_squash.go index f52a2301d906c..197d8102dd960 100644 --- a/services/pull/merge_squash.go +++ b/services/pull/merge_squash.go @@ -10,6 +10,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" ) @@ -24,7 +25,7 @@ func getAuthorSignatureSquash(ctx *mergeContext) (*git.Signature, error) { // Try to get an signature from the same user in one of the commits, as the // poster email might be private or commits might have a different signature // than the primary email address of the poster. - gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, ctx.tmpBasePath) + gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpenPath(ctx, ctx.tmpBasePath) if err != nil { log.Error("%-v Unable to open base repository: %v", ctx.pr, err) return nil, err diff --git a/services/pull/patch.go b/services/pull/patch.go index acaff04bda474..12b79a06253d1 100644 --- a/services/pull/patch.go +++ b/services/pull/patch.go @@ -19,6 +19,7 @@ import ( "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" @@ -35,7 +36,7 @@ func DownloadDiffOrPatch(ctx context.Context, pr *issues_model.PullRequest, w io return err } - gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, pr.BaseRepo.RepoPath()) + gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, pr.BaseRepo) if err != nil { return fmt.Errorf("OpenRepository: %w", err) } diff --git a/services/pull/pull.go b/services/pull/pull.go index c849deed2e289..eca0a360d79c9 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -615,7 +615,7 @@ func CloseBranchPulls(ctx context.Context, doer *user_model.User, repoID int64, // CloseRepoBranchesPulls close all pull requests which head branches are in the given repository, but only whose base repo is not in the given repository func CloseRepoBranchesPulls(ctx context.Context, doer *user_model.User, repo *repo_model.Repository) error { - branches, _, err := git.GetBranchesByPath(ctx, repo.RepoPath(), 0, 0) + branches, _, err := gitrepo.GetBranchesByPath(ctx, repo, 0, 0) if err != nil { return err } @@ -672,7 +672,7 @@ func GetSquashMergeCommitMessages(ctx context.Context, pr *issues_model.PullRequ } } - gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, pr.HeadRepo.RepoPath()) + gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, pr.HeadRepo) if err != nil { log.Error("Unable to open head repository: Error: %v", err) return "" @@ -883,7 +883,7 @@ func IsHeadEqualWithBranch(ctx context.Context, pr *issues_model.PullRequest, br if err = pr.LoadBaseRepo(ctx); err != nil { return false, err } - baseGitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, pr.BaseRepo.RepoPath()) + baseGitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, pr.BaseRepo) if err != nil { return false, err } @@ -903,7 +903,7 @@ func IsHeadEqualWithBranch(ctx context.Context, pr *issues_model.PullRequest, br } else { var closer io.Closer - headGitRepo, closer, err = git.RepositoryFromContextOrOpen(ctx, pr.HeadRepo.RepoPath()) + headGitRepo, closer, err = gitrepo.RepositoryFromContextOrOpen(ctx, pr.HeadRepo) if err != nil { return false, err } diff --git a/services/pull/review.go b/services/pull/review.go index e48f3801547dd..d4ea97561253e 100644 --- a/services/pull/review.go +++ b/services/pull/review.go @@ -16,6 +16,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" @@ -170,7 +171,7 @@ func createCodeComment(ctx context.Context, doer *user_model.User, repo *repo_mo if err := pr.LoadBaseRepo(ctx); err != nil { return nil, fmt.Errorf("LoadBaseRepo: %w", err) } - gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, pr.BaseRepo.RepoPath()) + gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, pr.BaseRepo) if err != nil { return nil, fmt.Errorf("RepositoryFromContextOrOpen: %w", err) } diff --git a/services/release/release.go b/services/release/release.go index f17682ae0f8f6..c1d13126f0b3b 100644 --- a/services/release/release.go +++ b/services/release/release.go @@ -16,6 +16,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/repository" @@ -168,7 +169,7 @@ func CreateNewTag(ctx context.Context, doer *user_model.User, repo *repo_model.R } } - gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.RepoPath()) + gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo) if err != nil { return err } diff --git a/services/repository/branch.go b/services/repository/branch.go index 63257c17604a9..9a75d58335bd8 100644 --- a/services/repository/branch.go +++ b/services/repository/branch.go @@ -191,10 +191,6 @@ func loadOneBranch(ctx context.Context, repo *repo_model.Repository, dbBranch *g }, nil } -func GetBranchCommitID(ctx context.Context, repo *repo_model.Repository, branch string) (string, error) { - return git.GetBranchCommitID(ctx, repo.RepoPath(), branch) -} - // checkBranchName validates branch name with existing repository branches func checkBranchName(ctx context.Context, repo *repo_model.Repository, name string) error { _, err := git.WalkReferences(ctx, repo.RepoPath(), func(_, refName string) error { diff --git a/services/repository/files/commit.go b/services/repository/files/commit.go index 048e41e6fdd38..16a15e06a7ccc 100644 --- a/services/repository/files/commit.go +++ b/services/repository/files/commit.go @@ -12,6 +12,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/services/automerge" ) @@ -23,7 +24,7 @@ func CreateCommitStatus(ctx context.Context, repo *repo_model.Repository, creato repoPath := repo.RepoPath() // confirm that commit is exist - gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.RepoPath()) + gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo) if err != nil { return fmt.Errorf("OpenRepository[%s]: %w", repoPath, err) } diff --git a/services/repository/files/content.go b/services/repository/files/content.go index 30d62fbcdf7c0..c278d7f8355cc 100644 --- a/services/repository/files/content.go +++ b/services/repository/files/content.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/models" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" @@ -58,7 +59,7 @@ func GetContentsOrList(ctx context.Context, repo *repo_model.Repository, treePat } treePath = cleanTreePath - gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.RepoPath()) + gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo) if err != nil { return nil, err } @@ -133,7 +134,7 @@ func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref } treePath = cleanTreePath - gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.RepoPath()) + gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo) if err != nil { return nil, err } diff --git a/services/repository/files/patch.go b/services/repository/files/patch.go index 14f8caaa8cf73..f6d5643dc91ce 100644 --- a/services/repository/files/patch.go +++ b/services/repository/files/patch.go @@ -13,6 +13,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/structs" asymkey_service "code.gitea.io/gitea/services/asymkey" @@ -42,7 +43,7 @@ func (opts *ApplyDiffPatchOptions) Validate(ctx context.Context, repo *repo_mode opts.NewBranch = opts.OldBranch } - gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.RepoPath()) + gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo) if err != nil { return err } diff --git a/services/repository/files/update.go b/services/repository/files/update.go index 1892043304e29..f223daf3a9fdf 100644 --- a/services/repository/files/update.go +++ b/services/repository/files/update.go @@ -16,6 +16,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -78,7 +79,7 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use opts.NewBranch = opts.OldBranch } - gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.RepoPath()) + gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo) if err != nil { return nil, err } From c411a3396bbb85d8a4ee3622f6674c07be4745fa Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 26 Jan 2024 15:22:20 +0800 Subject: [PATCH 08/18] More refactoring --- modules/git/repo_branch_gogit.go | 29 --------------------- modules/git/repo_branch_nogogit.go | 13 +++------- modules/gitrepo/gitrepo.go | 8 +++--- modules/gitrepo/walk_gogit.go | 41 ++++++++++++++++++++++++++++++ modules/gitrepo/walk_nogogit.go | 18 +++++++++++++ services/pull/pull.go | 2 +- services/repository/branch.go | 2 +- 7 files changed, 69 insertions(+), 44 deletions(-) create mode 100644 modules/gitrepo/walk_gogit.go create mode 100644 modules/gitrepo/walk_nogogit.go diff --git a/modules/git/repo_branch_gogit.go b/modules/git/repo_branch_gogit.go index 1c0d9a18aa9d9..d1ec14d81155f 100644 --- a/modules/git/repo_branch_gogit.go +++ b/modules/git/repo_branch_gogit.go @@ -7,7 +7,6 @@ package git import ( - "context" "sort" "strings" @@ -95,34 +94,6 @@ func (repo *Repository) GetBranchNames(skip, limit int) ([]string, int, error) { return branchNames, len(branchData), nil } -// WalkReferences walks all the references from the repository -// refType should be empty, ObjectTag or ObjectBranch. All other values are equivalent to empty. -func WalkReferences(ctx context.Context, repoPath string, walkfn func(sha1, refname string) error) (int, error) { - repo := RepositoryFromContext(ctx, repoPath) - if repo == nil { - var err error - repo, err = OpenRepository(ctx, repoPath) - if err != nil { - return 0, err - } - defer repo.Close() - } - - i := 0 - iter, err := repo.gogitRepo.References() - if err != nil { - return i, err - } - defer iter.Close() - - err = iter.ForEach(func(ref *plumbing.Reference) error { - err := walkfn(ref.Hash().String(), string(ref.Name())) - i++ - return err - }) - return i, err -} - // WalkReferences walks all the references from the repository func (repo *Repository) WalkReferences(arg ObjectType, skip, limit int, walkfn func(sha1, refname string) error) (int, error) { i := 0 diff --git a/modules/git/repo_branch_nogogit.go b/modules/git/repo_branch_nogogit.go index b1e7c8b73e640..470faebe25f79 100644 --- a/modules/git/repo_branch_nogogit.go +++ b/modules/git/repo_branch_nogogit.go @@ -65,11 +65,6 @@ func (repo *Repository) GetBranchNames(skip, limit int) ([]string, int, error) { return callShowRef(repo.Ctx, repo.Path, BranchPrefix, TrustedCmdArgs{BranchPrefix, "--sort=-committerdate"}, skip, limit) } -// WalkReferences walks all the references from the repository -func WalkReferences(ctx context.Context, repoPath string, walkfn func(sha1, refname string) error) (int, error) { - return walkShowRef(ctx, repoPath, nil, 0, 0, walkfn) -} - // WalkReferences walks all the references from the repository // refType should be empty, ObjectTag or ObjectBranch. All other values are equivalent to empty. func (repo *Repository) WalkReferences(refType ObjectType, skip, limit int, walkfn func(sha1, refname string) error) (int, error) { @@ -81,12 +76,12 @@ func (repo *Repository) WalkReferences(refType ObjectType, skip, limit int, walk args = TrustedCmdArgs{BranchPrefix, "--sort=-committerdate"} } - return walkShowRef(repo.Ctx, repo.Path, args, skip, limit, walkfn) + return WalkShowRef(repo.Ctx, repo.Path, args, skip, limit, walkfn) } // callShowRef return refs, if limit = 0 it will not limit func callShowRef(ctx context.Context, repoPath, trimPrefix string, extraArgs TrustedCmdArgs, skip, limit int) (branchNames []string, countAll int, err error) { - countAll, err = walkShowRef(ctx, repoPath, extraArgs, skip, limit, func(_, branchName string) error { + countAll, err = WalkShowRef(ctx, repoPath, extraArgs, skip, limit, func(_, branchName string) error { branchName = strings.TrimPrefix(branchName, trimPrefix) branchNames = append(branchNames, branchName) @@ -95,7 +90,7 @@ func callShowRef(ctx context.Context, repoPath, trimPrefix string, extraArgs Tru return branchNames, countAll, err } -func walkShowRef(ctx context.Context, repoPath string, extraArgs TrustedCmdArgs, skip, limit int, walkfn func(sha1, refname string) error) (countAll int, err error) { +func WalkShowRef(ctx context.Context, repoPath string, extraArgs TrustedCmdArgs, skip, limit int, walkfn func(sha1, refname string) error) (countAll int, err error) { stdoutReader, stdoutWriter := io.Pipe() defer func() { _ = stdoutReader.Close() @@ -189,7 +184,7 @@ func walkShowRef(ctx context.Context, repoPath string, extraArgs TrustedCmdArgs, // GetRefsBySha returns all references filtered with prefix that belong to a sha commit hash func (repo *Repository) GetRefsBySha(sha, prefix string) ([]string, error) { var revList []string - _, err := walkShowRef(repo.Ctx, repo.Path, nil, 0, 0, func(walkSha, refname string) error { + _, err := WalkShowRef(repo.Ctx, repo.Path, nil, 0, 0, func(walkSha, refname string) error { if walkSha == sha && strings.HasPrefix(refname, prefix) { revList = append(revList, refname) } diff --git a/modules/gitrepo/gitrepo.go b/modules/gitrepo/gitrepo.go index 7fcc4495a7a66..522d8f76a561d 100644 --- a/modules/gitrepo/gitrepo.go +++ b/modules/gitrepo/gitrepo.go @@ -16,12 +16,12 @@ import ( type Repository = git.Repository // OpenRepository opens the repository at the given relative path with the provided context. -func OpenRepository(ctx context.Context, repoPath *repo_model.Repository) (*Repository, error) { - return git.OpenRepository(ctx, repoPath.RepoPath()) +func OpenRepository(ctx context.Context, repo *repo_model.Repository) (*Repository, error) { + return git.OpenRepository(ctx, repo.RepoPath()) } -func OpenWikiRepository(ctx context.Context, repoPath *repo_model.Repository) (*Repository, error) { - return git.OpenRepository(ctx, repoPath.WikiPath()) +func OpenWikiRepository(ctx context.Context, repo *repo_model.Repository) (*Repository, error) { + return git.OpenRepository(ctx, repo.WikiPath()) } // DeleteRepository deletes the repository at the given relative path with the provided context. diff --git a/modules/gitrepo/walk_gogit.go b/modules/gitrepo/walk_gogit.go new file mode 100644 index 0000000000000..fbc6aef38fba8 --- /dev/null +++ b/modules/gitrepo/walk_gogit.go @@ -0,0 +1,41 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +//go:build gogit + +package gitrepo + +import ( + "context" + + repo_model "code.gitea.io/gitea/models/repo" + "github.com/go-git/go-git/plumbing" +) + +// WalkReferences walks all the references from the repository +// refType should be empty, ObjectTag or ObjectBranch. All other values are equivalent to empty. +func WalkReferences(ctx context.Context, repo *repo_model.Repository, walkfn func(sha1, refname string) error) (int, error) { + repo := RepositoryFromContext(ctx, repo) + if repo == nil { + var err error + repo, err = OpenRepository(ctx, repo) + if err != nil { + return 0, err + } + defer repo.Close() + } + + i := 0 + iter, err := repo.gogitRepo.References() + if err != nil { + return i, err + } + defer iter.Close() + + err = iter.ForEach(func(ref *plumbing.Reference) error { + err := walkfn(ref.Hash().String(), string(ref.Name())) + i++ + return err + }) + return i, err +} diff --git a/modules/gitrepo/walk_nogogit.go b/modules/gitrepo/walk_nogogit.go new file mode 100644 index 0000000000000..d83182bc2be5e --- /dev/null +++ b/modules/gitrepo/walk_nogogit.go @@ -0,0 +1,18 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +//go:build !gogit + +package gitrepo + +import ( + "context" + + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/modules/git" +) + +// WalkReferences walks all the references from the repository +func WalkReferences(ctx context.Context, repo *repo_model.Repository, walkfn func(sha1, refname string) error) (int, error) { + return git.WalkShowRef(ctx, repo.RepoPath(), nil, 0, 0, walkfn) +} diff --git a/services/pull/pull.go b/services/pull/pull.go index eca0a360d79c9..e1ea4357fc5d2 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -272,7 +272,7 @@ func checkForInvalidation(ctx context.Context, requests issues_model.PullRequest } gitRepo, err := gitrepo.OpenRepository(ctx, repo) if err != nil { - return fmt.Errorf("git.OpenRepository: %w", err) + return fmt.Errorf("gitrepo.OpenRepository: %w", err) } go func() { // FIXME: graceful: We need to tell the manager we're doing something... diff --git a/services/repository/branch.go b/services/repository/branch.go index 9a75d58335bd8..e2e50297afacd 100644 --- a/services/repository/branch.go +++ b/services/repository/branch.go @@ -193,7 +193,7 @@ func loadOneBranch(ctx context.Context, repo *repo_model.Repository, dbBranch *g // checkBranchName validates branch name with existing repository branches func checkBranchName(ctx context.Context, repo *repo_model.Repository, name string) error { - _, err := git.WalkReferences(ctx, repo.RepoPath(), func(_, refName string) error { + _, err := gitrepo.WalkReferences(ctx, repo, func(_, refName string) error { branchRefName := strings.TrimPrefix(refName, git.BranchPrefix) switch { case branchRefName == name: From 9ba182ca11473b860672b6d2d3996cd980f18f4e Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 26 Jan 2024 15:32:37 +0800 Subject: [PATCH 09/18] Fix build --- modules/gitrepo/walk_gogit.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/gitrepo/walk_gogit.go b/modules/gitrepo/walk_gogit.go index fbc6aef38fba8..aea49d7c45da4 100644 --- a/modules/gitrepo/walk_gogit.go +++ b/modules/gitrepo/walk_gogit.go @@ -9,7 +9,7 @@ import ( "context" repo_model "code.gitea.io/gitea/models/repo" - "github.com/go-git/go-git/plumbing" + "github.com/go-git/go-git/v5/plumbing" ) // WalkReferences walks all the references from the repository From 6f7224362dfb8179d6ff887d4943cc07b35cba06 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 26 Jan 2024 15:50:37 +0800 Subject: [PATCH 10/18] Fix lint gogit --- modules/gitrepo/walk_gogit.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/gitrepo/walk_gogit.go b/modules/gitrepo/walk_gogit.go index aea49d7c45da4..8fe8acc2eee5e 100644 --- a/modules/gitrepo/walk_gogit.go +++ b/modules/gitrepo/walk_gogit.go @@ -15,18 +15,18 @@ import ( // WalkReferences walks all the references from the repository // refType should be empty, ObjectTag or ObjectBranch. All other values are equivalent to empty. func WalkReferences(ctx context.Context, repo *repo_model.Repository, walkfn func(sha1, refname string) error) (int, error) { - repo := RepositoryFromContext(ctx, repo) - if repo == nil { + gitRepo := RepositoryFromContext(ctx, repo) + if gitRepo == nil { var err error - repo, err = OpenRepository(ctx, repo) + gitRepo, err = OpenRepository(ctx, repo) if err != nil { return 0, err } - defer repo.Close() + defer gitRepo.Close() } i := 0 - iter, err := repo.gogitRepo.References() + iter, err := gitRepo.gogitRepo.References() if err != nil { return i, err } From 74026797e5846c8943f2644f2de8754c1f364eea Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 26 Jan 2024 16:43:41 +0800 Subject: [PATCH 11/18] Fix checks --- modules/gitrepo/walk_gogit.go | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/gitrepo/walk_gogit.go b/modules/gitrepo/walk_gogit.go index 8fe8acc2eee5e..17e808350732b 100644 --- a/modules/gitrepo/walk_gogit.go +++ b/modules/gitrepo/walk_gogit.go @@ -9,6 +9,7 @@ import ( "context" repo_model "code.gitea.io/gitea/models/repo" + "github.com/go-git/go-git/v5/plumbing" ) From 236fdf172b3871d55ae9f9138324bfc0db533931 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 26 Jan 2024 16:46:20 +0800 Subject: [PATCH 12/18] Fix lint --- modules/gitrepo/walk_gogit.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/gitrepo/walk_gogit.go b/modules/gitrepo/walk_gogit.go index 17e808350732b..c714aa0693497 100644 --- a/modules/gitrepo/walk_gogit.go +++ b/modules/gitrepo/walk_gogit.go @@ -27,7 +27,7 @@ func WalkReferences(ctx context.Context, repo *repo_model.Repository, walkfn fun } i := 0 - iter, err := gitRepo.gogitRepo.References() + iter, err := gitRepo.GoGitRepo().References() if err != nil { return i, err } From 20ac4f094fa49dbc47e02d21b9734223465288ea Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 27 Jan 2024 11:43:13 +0800 Subject: [PATCH 13/18] Apply suggestions from code review Co-authored-by: delvh --- modules/gitrepo/branch.go | 2 +- modules/gitrepo/gitrepo.go | 4 ++-- modules/gitrepo/walk_gogit.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/gitrepo/branch.go b/modules/gitrepo/branch.go index 8f22181b64a7a..e0e55bdbe94c8 100644 --- a/modules/gitrepo/branch.go +++ b/modules/gitrepo/branch.go @@ -10,7 +10,7 @@ import ( "code.gitea.io/gitea/modules/git" ) -// GetBranchesByPath returns a branch by it's path +// GetBranchesByPath returns a branch by its path // if limit = 0 it will not limit func GetBranchesByPath(ctx context.Context, repo *repo_model.Repository, skip, limit int) ([]*git.Branch, int, error) { gitRepo, err := OpenRepository(ctx, repo) diff --git a/modules/gitrepo/gitrepo.go b/modules/gitrepo/gitrepo.go index 522d8f76a561d..a85478159ded6 100644 --- a/modules/gitrepo/gitrepo.go +++ b/modules/gitrepo/gitrepo.go @@ -47,7 +47,7 @@ func RepositoryFromContext(ctx context.Context, repo *repo_model.Repository) *Re return nil } - if gitRepo, ok := value.(*Repository); ok && gitRepo != nil { + if gitRepo, ok := value.(*Repository); ok { if gitRepo.Path == repo.RepoPath() { return gitRepo } @@ -78,7 +78,7 @@ func repositoryFromContext(ctx context.Context, path string) *git.Repository { return nil } - if repo, ok := value.(*git.Repository); ok && repo != nil { + if repo, ok := value.(*git.Repository); ok { if repo.Path == path { return repo } diff --git a/modules/gitrepo/walk_gogit.go b/modules/gitrepo/walk_gogit.go index c714aa0693497..4301fcb911a27 100644 --- a/modules/gitrepo/walk_gogit.go +++ b/modules/gitrepo/walk_gogit.go @@ -14,7 +14,7 @@ import ( ) // WalkReferences walks all the references from the repository -// refType should be empty, ObjectTag or ObjectBranch. All other values are equivalent to empty. +// refname is empty, ObjectTag or ObjectBranch. All other values should be treated as equivalent to empty. func WalkReferences(ctx context.Context, repo *repo_model.Repository, walkfn func(sha1, refname string) error) (int, error) { gitRepo := RepositoryFromContext(ctx, repo) if gitRepo == nil { From 4b8af156024b760dfbfbc23e252fbe452744cd70 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 27 Jan 2024 19:50:03 +0800 Subject: [PATCH 14/18] Fix test --- modules/gitrepo/gitrepo.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/gitrepo/gitrepo.go b/modules/gitrepo/gitrepo.go index a85478159ded6..2f96846579c50 100644 --- a/modules/gitrepo/gitrepo.go +++ b/modules/gitrepo/gitrepo.go @@ -41,13 +41,13 @@ type contextKey struct { var RepositoryContextKey = &contextKey{"repository"} // RepositoryFromContext attempts to get the repository from the context -func RepositoryFromContext(ctx context.Context, repo *repo_model.Repository) *Repository { +func repositoryFromContext(ctx context.Context, repo *repo_model.Repository) *Repository { value := ctx.Value(RepositoryContextKey) if value == nil { return nil } - if gitRepo, ok := value.(*Repository); ok { + if gitRepo, ok := value.(*Repository); ok && gitRepo != nil { if gitRepo.Path == repo.RepoPath() { return gitRepo } @@ -62,7 +62,7 @@ func (nopCloser) Close() error { return nil } // RepositoryFromContextOrOpen attempts to get the repository from the context or just opens it func RepositoryFromContextOrOpen(ctx context.Context, repo *repo_model.Repository) (*Repository, io.Closer, error) { - gitRepo := RepositoryFromContext(ctx, repo) + gitRepo := repositoryFromContext(ctx, repo) if gitRepo != nil { return gitRepo, nopCloser(nil), nil } @@ -71,14 +71,14 @@ func RepositoryFromContextOrOpen(ctx context.Context, repo *repo_model.Repositor return gitRepo, gitRepo, err } -// RepositoryFromContext attempts to get the repository from the context -func repositoryFromContext(ctx context.Context, path string) *git.Repository { +// repositoryFromContextPath attempts to get the repository from the context +func repositoryFromContextPath(ctx context.Context, path string) *git.Repository { value := ctx.Value(RepositoryContextKey) if value == nil { return nil } - if repo, ok := value.(*git.Repository); ok { + if repo, ok := value.(*git.Repository); ok && repo != nil { if repo.Path == path { return repo } @@ -90,7 +90,7 @@ func repositoryFromContext(ctx context.Context, path string) *git.Repository { // RepositoryFromContextOrOpenPath attempts to get the repository from the context or just opens it // Deprecated: Use RepositoryFromContextOrOpen instead func RepositoryFromContextOrOpenPath(ctx context.Context, path string) (*git.Repository, io.Closer, error) { - gitRepo := repositoryFromContext(ctx, path) + gitRepo := repositoryFromContextPath(ctx, path) if gitRepo != nil { return gitRepo, nopCloser(nil), nil } From 64a6c61988620f7e2b8e3cbdc1c6598448a7fd64 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 27 Jan 2024 20:27:09 +0800 Subject: [PATCH 15/18] Fix lint --- modules/gitrepo/walk_gogit.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/gitrepo/walk_gogit.go b/modules/gitrepo/walk_gogit.go index 4301fcb911a27..44fc7a3e503aa 100644 --- a/modules/gitrepo/walk_gogit.go +++ b/modules/gitrepo/walk_gogit.go @@ -16,7 +16,7 @@ import ( // WalkReferences walks all the references from the repository // refname is empty, ObjectTag or ObjectBranch. All other values should be treated as equivalent to empty. func WalkReferences(ctx context.Context, repo *repo_model.Repository, walkfn func(sha1, refname string) error) (int, error) { - gitRepo := RepositoryFromContext(ctx, repo) + gitRepo := repositoryFromContext(ctx, repo) if gitRepo == nil { var err error gitRepo, err = OpenRepository(ctx, repo) From 18b26289f2881ec9f23b0f249da5f82a1b6e5cba Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 27 Jan 2024 21:42:18 +0800 Subject: [PATCH 16/18] Use repository interface but not depend on a special model package --- modules/gitrepo/branch.go | 5 ++--- modules/gitrepo/gitrepo.go | 40 +++++++++++++++++---------------- modules/gitrepo/walk_gogit.go | 4 +--- modules/gitrepo/walk_nogogit.go | 5 ++--- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/modules/gitrepo/branch.go b/modules/gitrepo/branch.go index e0e55bdbe94c8..dcaf92668d158 100644 --- a/modules/gitrepo/branch.go +++ b/modules/gitrepo/branch.go @@ -6,13 +6,12 @@ package gitrepo import ( "context" - repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" ) // GetBranchesByPath returns a branch by its path // if limit = 0 it will not limit -func GetBranchesByPath(ctx context.Context, repo *repo_model.Repository, skip, limit int) ([]*git.Branch, int, error) { +func GetBranchesByPath(ctx context.Context, repo Repository, skip, limit int) ([]*git.Branch, int, error) { gitRepo, err := OpenRepository(ctx, repo) if err != nil { return nil, 0, err @@ -22,7 +21,7 @@ func GetBranchesByPath(ctx context.Context, repo *repo_model.Repository, skip, l return gitRepo.GetBranches(skip, limit) } -func GetBranchCommitID(ctx context.Context, repo *repo_model.Repository, branch string) (string, error) { +func GetBranchCommitID(ctx context.Context, repo Repository, branch string) (string, error) { gitRepo, err := OpenRepository(ctx, repo) if err != nil { return "", err diff --git a/modules/gitrepo/gitrepo.go b/modules/gitrepo/gitrepo.go index 2f96846579c50..8bfdda251bf87 100644 --- a/modules/gitrepo/gitrepo.go +++ b/modules/gitrepo/gitrepo.go @@ -5,31 +5,33 @@ package gitrepo import ( "context" - "fmt" "io" + "path/filepath" + "strings" - repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/setting" ) -type Repository = git.Repository +type Repository interface { + FullName() string +} -// OpenRepository opens the repository at the given relative path with the provided context. -func OpenRepository(ctx context.Context, repo *repo_model.Repository) (*Repository, error) { - return git.OpenRepository(ctx, repo.RepoPath()) +func repoPath(fullName string) string { + return filepath.Join(setting.RepoRootPath, strings.ToLower(fullName)+".git") } -func OpenWikiRepository(ctx context.Context, repo *repo_model.Repository) (*Repository, error) { - return git.OpenRepository(ctx, repo.WikiPath()) +func wikiPath(fullName string) string { + return filepath.Join(setting.RepoRootPath, strings.ToLower(fullName)+".wiki.git") } -// DeleteRepository deletes the repository at the given relative path with the provided context. -func DeleteRepository(ctx context.Context, repo *repo_model.Repository) error { - if err := util.RemoveAll(repo.RepoPath()); err != nil { - return fmt.Errorf("failed to remove %s: %w", repo.FullName(), err) - } - return nil +// OpenRepository opens the repository at the given relative path with the provided context. +func OpenRepository(ctx context.Context, repo Repository) (*git.Repository, error) { + return git.OpenRepository(ctx, repoPath(repo.FullName())) +} + +func OpenWikiRepository(ctx context.Context, repo Repository) (*git.Repository, error) { + return git.OpenRepository(ctx, wikiPath(repo.FullName())) } // contextKey is a value for use with context.WithValue. @@ -41,14 +43,14 @@ type contextKey struct { var RepositoryContextKey = &contextKey{"repository"} // RepositoryFromContext attempts to get the repository from the context -func repositoryFromContext(ctx context.Context, repo *repo_model.Repository) *Repository { +func repositoryFromContext(ctx context.Context, repo Repository) *git.Repository { value := ctx.Value(RepositoryContextKey) if value == nil { return nil } - if gitRepo, ok := value.(*Repository); ok && gitRepo != nil { - if gitRepo.Path == repo.RepoPath() { + if gitRepo, ok := value.(*git.Repository); ok && gitRepo != nil { + if gitRepo.Path == repoPath(repo.FullName()) { return gitRepo } } @@ -61,7 +63,7 @@ type nopCloser func() func (nopCloser) Close() error { return nil } // RepositoryFromContextOrOpen attempts to get the repository from the context or just opens it -func RepositoryFromContextOrOpen(ctx context.Context, repo *repo_model.Repository) (*Repository, io.Closer, error) { +func RepositoryFromContextOrOpen(ctx context.Context, repo Repository) (*git.Repository, io.Closer, error) { gitRepo := repositoryFromContext(ctx, repo) if gitRepo != nil { return gitRepo, nopCloser(nil), nil diff --git a/modules/gitrepo/walk_gogit.go b/modules/gitrepo/walk_gogit.go index 44fc7a3e503aa..6370faf08e7df 100644 --- a/modules/gitrepo/walk_gogit.go +++ b/modules/gitrepo/walk_gogit.go @@ -8,14 +8,12 @@ package gitrepo import ( "context" - repo_model "code.gitea.io/gitea/models/repo" - "github.com/go-git/go-git/v5/plumbing" ) // WalkReferences walks all the references from the repository // refname is empty, ObjectTag or ObjectBranch. All other values should be treated as equivalent to empty. -func WalkReferences(ctx context.Context, repo *repo_model.Repository, walkfn func(sha1, refname string) error) (int, error) { +func WalkReferences(ctx context.Context, repo Repository, walkfn func(sha1, refname string) error) (int, error) { gitRepo := repositoryFromContext(ctx, repo) if gitRepo == nil { var err error diff --git a/modules/gitrepo/walk_nogogit.go b/modules/gitrepo/walk_nogogit.go index d83182bc2be5e..562b25b16f48a 100644 --- a/modules/gitrepo/walk_nogogit.go +++ b/modules/gitrepo/walk_nogogit.go @@ -8,11 +8,10 @@ package gitrepo import ( "context" - repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" ) // WalkReferences walks all the references from the repository -func WalkReferences(ctx context.Context, repo *repo_model.Repository, walkfn func(sha1, refname string) error) (int, error) { - return git.WalkShowRef(ctx, repo.RepoPath(), nil, 0, 0, walkfn) +func WalkReferences(ctx context.Context, repo Repository, walkfn func(sha1, refname string) error) (int, error) { + return git.WalkShowRef(ctx, repoPath(repo.FullName()), nil, 0, 0, walkfn) } From e8e7f5a7afa49162a209d74ffb753120927c2d23 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 27 Jan 2024 22:33:31 +0800 Subject: [PATCH 17/18] Fix repoPath --- modules/gitrepo/gitrepo.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/gitrepo/gitrepo.go b/modules/gitrepo/gitrepo.go index 8bfdda251bf87..e4fdb1cd4b886 100644 --- a/modules/gitrepo/gitrepo.go +++ b/modules/gitrepo/gitrepo.go @@ -6,6 +6,7 @@ package gitrepo import ( "context" "io" + "path" "path/filepath" "strings" @@ -14,15 +15,17 @@ import ( ) type Repository interface { - FullName() string + FullName() string // should return "/" } func repoPath(fullName string) string { - return filepath.Join(setting.RepoRootPath, strings.ToLower(fullName)+".git") + ownerName, repoName := path.Split(fullName) + return filepath.Join(setting.RepoRootPath, strings.ToLower(ownerName), strings.ToLower(repoName)+".git") } func wikiPath(fullName string) string { - return filepath.Join(setting.RepoRootPath, strings.ToLower(fullName)+".wiki.git") + ownerName, repoName := path.Split(fullName) + return filepath.Join(setting.RepoRootPath, strings.ToLower(ownerName), strings.ToLower(repoName)+".wiki.git") } // OpenRepository opens the repository at the given relative path with the provided context. From dc08148967bfdcb020b896c7dd2e2c60f68e15b9 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 27 Jan 2024 22:43:07 +0800 Subject: [PATCH 18/18] Use a better interface repository --- models/repo/repo.go | 8 ++++++++ modules/gitrepo/gitrepo.go | 20 +++++++++----------- modules/gitrepo/walk_nogogit.go | 2 +- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/models/repo/repo.go b/models/repo/repo.go index 4401041cdd528..13493ba6e80e6 100644 --- a/models/repo/repo.go +++ b/models/repo/repo.go @@ -196,6 +196,14 @@ func init() { db.RegisterModel(new(Repository)) } +func (repo *Repository) GetName() string { + return repo.Name +} + +func (repo *Repository) GetOwnerName() string { + return repo.OwnerName +} + // SanitizedOriginalURL returns a sanitized OriginalURL func (repo *Repository) SanitizedOriginalURL() string { if repo.OriginalURL == "" { diff --git a/modules/gitrepo/gitrepo.go b/modules/gitrepo/gitrepo.go index e4fdb1cd4b886..d89f8f9c0c88c 100644 --- a/modules/gitrepo/gitrepo.go +++ b/modules/gitrepo/gitrepo.go @@ -6,7 +6,6 @@ package gitrepo import ( "context" "io" - "path" "path/filepath" "strings" @@ -15,26 +14,25 @@ import ( ) type Repository interface { - FullName() string // should return "/" + GetName() string + GetOwnerName() string } -func repoPath(fullName string) string { - ownerName, repoName := path.Split(fullName) - return filepath.Join(setting.RepoRootPath, strings.ToLower(ownerName), strings.ToLower(repoName)+".git") +func repoPath(repo Repository) string { + return filepath.Join(setting.RepoRootPath, strings.ToLower(repo.GetOwnerName()), strings.ToLower(repo.GetName())+".git") } -func wikiPath(fullName string) string { - ownerName, repoName := path.Split(fullName) - return filepath.Join(setting.RepoRootPath, strings.ToLower(ownerName), strings.ToLower(repoName)+".wiki.git") +func wikiPath(repo Repository) string { + return filepath.Join(setting.RepoRootPath, strings.ToLower(repo.GetOwnerName()), strings.ToLower(repo.GetName())+".wiki.git") } // OpenRepository opens the repository at the given relative path with the provided context. func OpenRepository(ctx context.Context, repo Repository) (*git.Repository, error) { - return git.OpenRepository(ctx, repoPath(repo.FullName())) + return git.OpenRepository(ctx, repoPath(repo)) } func OpenWikiRepository(ctx context.Context, repo Repository) (*git.Repository, error) { - return git.OpenRepository(ctx, wikiPath(repo.FullName())) + return git.OpenRepository(ctx, wikiPath(repo)) } // contextKey is a value for use with context.WithValue. @@ -53,7 +51,7 @@ func repositoryFromContext(ctx context.Context, repo Repository) *git.Repository } if gitRepo, ok := value.(*git.Repository); ok && gitRepo != nil { - if gitRepo.Path == repoPath(repo.FullName()) { + if gitRepo.Path == repoPath(repo) { return gitRepo } } diff --git a/modules/gitrepo/walk_nogogit.go b/modules/gitrepo/walk_nogogit.go index 562b25b16f48a..ff9555996dff5 100644 --- a/modules/gitrepo/walk_nogogit.go +++ b/modules/gitrepo/walk_nogogit.go @@ -13,5 +13,5 @@ import ( // WalkReferences walks all the references from the repository func WalkReferences(ctx context.Context, repo Repository, walkfn func(sha1, refname string) error) (int, error) { - return git.WalkShowRef(ctx, repoPath(repo.FullName()), nil, 0, 0, walkfn) + return git.WalkShowRef(ctx, repoPath(repo), nil, 0, 0, walkfn) }