From 9c673d066c2018e70e3eb0532af630fff2fc5b7a Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 13 Mar 2025 20:00:56 -0700 Subject: [PATCH] Add abstraction layer to check if the repository exists on disk (#33874) Extract from #28966 This PR uses `gitrepo.IsRepositoryExist` instead of `util.IsExist` to detect whether the repository exist in disk. This will move `RepoPath` detail behind of package `gitrepo` to make it easier to do possible changes where storing the repositories. No code change --- modules/gitrepo/gitrepo.go | 5 +++++ modules/repository/init.go | 16 ++++++++-------- services/repository/adopt.go | 20 +++++++++---------- services/repository/create.go | 34 ++++++++++++++++----------------- services/repository/fork.go | 6 ++---- services/repository/generate.go | 11 +++++------ 6 files changed, 45 insertions(+), 47 deletions(-) diff --git a/modules/gitrepo/gitrepo.go b/modules/gitrepo/gitrepo.go index 540b724489..c3b412fd83 100644 --- a/modules/gitrepo/gitrepo.go +++ b/modules/gitrepo/gitrepo.go @@ -69,3 +69,8 @@ func RepositoryFromRequestContextOrOpen(ctx reqctx.RequestContext, repo Reposito ctx.SetContextValue(ck, gitRepo) return gitRepo, nil } + +// IsRepositoryExist returns true if the repository directory exists in the disk +func IsRepositoryExist(ctx context.Context, repo Repository) (bool, error) { + return util.IsExist(repoPath(repo)) +} diff --git a/modules/repository/init.go b/modules/repository/init.go index 24602ae090..772ae3efe3 100644 --- a/modules/repository/init.go +++ b/modules/repository/init.go @@ -13,6 +13,7 @@ import ( issues_model "code.gitea.io/gitea/models/issues" 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/label" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/options" @@ -120,25 +121,24 @@ func LoadRepoConfig() error { return nil } -func CheckInitRepository(ctx context.Context, owner, name, objectFormatName string) (err error) { +func CheckInitRepository(ctx context.Context, repo *repo_model.Repository) (err error) { // Somehow the directory could exist. - repoPath := repo_model.RepoPath(owner, name) - isExist, err := util.IsExist(repoPath) + isExist, err := gitrepo.IsRepositoryExist(ctx, repo) if err != nil { - log.Error("Unable to check if %s exists. Error: %v", repoPath, err) + log.Error("Unable to check if %s exists. Error: %v", repo.FullName(), err) return err } if isExist { return repo_model.ErrRepoFilesAlreadyExist{ - Uname: owner, - Name: name, + Uname: repo.OwnerName, + Name: repo.Name, } } // Init git bare new repository. - if err = git.InitRepository(ctx, repoPath, true, objectFormatName); err != nil { + if err = git.InitRepository(ctx, repo.RepoPath(), true, repo.ObjectFormatName); err != nil { return fmt.Errorf("git.InitRepository: %w", err) - } else if err = CreateDelegateHooks(repoPath); err != nil { + } else if err = CreateDelegateHooks(repo.RepoPath()); err != nil { return fmt.Errorf("createDelegateHooks: %w", err) } return nil diff --git a/services/repository/adopt.go b/services/repository/adopt.go index 40a1327e5e..729441c9f1 100644 --- a/services/repository/adopt.go +++ b/services/repository/adopt.go @@ -52,12 +52,10 @@ func AdoptRepository(ctx context.Context, doer, u *user_model.User, opts CreateR IsEmpty: !opts.AutoInit, } - repoPath := repo_model.RepoPath(u.Name, repo.Name) - if err := db.WithTx(ctx, func(ctx context.Context) error { - isExist, err := util.IsExist(repoPath) + isExist, err := gitrepo.IsRepositoryExist(ctx, repo) if err != nil { - log.Error("Unable to check if %s exists. Error: %v", repoPath, err) + log.Error("Unable to check if %s exists. Error: %v", repo.FullName(), err) return err } if !isExist { @@ -82,7 +80,7 @@ func AdoptRepository(ctx context.Context, doer, u *user_model.User, opts CreateR } if err := func() error { - if err := adoptRepository(ctx, repoPath, repo, opts.DefaultBranch); err != nil { + if err := adoptRepository(ctx, repo, opts.DefaultBranch); err != nil { return fmt.Errorf("adoptRepository: %w", err) } @@ -91,7 +89,7 @@ func AdoptRepository(ctx context.Context, doer, u *user_model.User, opts CreateR } if stdout, _, err := git.NewCommand("update-server-info"). - RunStdString(ctx, &git.RunOpts{Dir: repoPath}); err != nil { + RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}); err != nil { log.Error("CreateRepository(git update-server-info) in %v: Stdout: %s\nError: %v", repo, stdout, err) return fmt.Errorf("CreateRepository(git update-server-info): %w", err) } @@ -107,17 +105,17 @@ func AdoptRepository(ctx context.Context, doer, u *user_model.User, opts CreateR return repo, nil } -func adoptRepository(ctx context.Context, repoPath string, repo *repo_model.Repository, defaultBranch string) (err error) { - isExist, err := util.IsExist(repoPath) +func adoptRepository(ctx context.Context, repo *repo_model.Repository, defaultBranch string) (err error) { + isExist, err := gitrepo.IsRepositoryExist(ctx, repo) if err != nil { - log.Error("Unable to check if %s exists. Error: %v", repoPath, err) + log.Error("Unable to check if %s exists. Error: %v", repo.FullName(), err) return err } if !isExist { - return fmt.Errorf("adoptRepository: path does not already exist: %s", repoPath) + return fmt.Errorf("adoptRepository: path does not already exist: %s", repo.FullName()) } - if err := repo_module.CreateDelegateHooks(repoPath); err != nil { + if err := repo_module.CreateDelegateHooks(repo.RepoPath()); err != nil { return fmt.Errorf("createDelegateHooks: %w", err) } diff --git a/services/repository/create.go b/services/repository/create.go index aa4c3905d4..62b5931fd9 100644 --- a/services/repository/create.go +++ b/services/repository/create.go @@ -52,7 +52,7 @@ type CreateRepoOptions struct { ObjectFormatName string } -func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir, repoPath string, opts CreateRepoOptions) error { +func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir string, opts CreateRepoOptions) error { commitTimeStr := time.Now().Format(time.RFC3339) authorSig := repo.Owner.NewGitSig() @@ -67,7 +67,7 @@ func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir, ) // Clone to temporary path and do the init commit. - if stdout, _, err := git.NewCommand("clone").AddDynamicArguments(repoPath, tmpDir). + if stdout, _, err := git.NewCommand("clone").AddDynamicArguments(repo.RepoPath(), tmpDir). RunStdString(ctx, &git.RunOpts{Dir: "", Env: env}); err != nil { log.Error("Failed to clone from %v into %s: stdout: %s\nError: %v", repo, tmpDir, stdout, err) return fmt.Errorf("git clone: %w", err) @@ -139,8 +139,8 @@ func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir, } // InitRepository initializes README and .gitignore if needed. -func initRepository(ctx context.Context, repoPath string, u *user_model.User, repo *repo_model.Repository, opts CreateRepoOptions) (err error) { - if err = repo_module.CheckInitRepository(ctx, repo.OwnerName, repo.Name, opts.ObjectFormatName); err != nil { +func initRepository(ctx context.Context, u *user_model.User, repo *repo_model.Repository, opts CreateRepoOptions) (err error) { + if err = repo_module.CheckInitRepository(ctx, repo); err != nil { return err } @@ -148,7 +148,7 @@ func initRepository(ctx context.Context, repoPath string, u *user_model.User, re if opts.AutoInit { tmpDir, err := os.MkdirTemp(os.TempDir(), "gitea-"+repo.Name) if err != nil { - return fmt.Errorf("Failed to create temp dir for repository %s: %w", repo.RepoPath(), err) + return fmt.Errorf("Failed to create temp dir for repository %s: %w", repo.FullName(), err) } defer func() { if err := util.RemoveAll(tmpDir); err != nil { @@ -156,7 +156,7 @@ func initRepository(ctx context.Context, repoPath string, u *user_model.User, re } }() - if err = prepareRepoCommit(ctx, repo, tmpDir, repoPath, opts); err != nil { + if err = prepareRepoCommit(ctx, repo, tmpDir, opts); err != nil { return fmt.Errorf("prepareRepoCommit: %w", err) } @@ -256,10 +256,9 @@ func CreateRepositoryDirectly(ctx context.Context, doer, u *user_model.User, opt return nil } - repoPath := repo_model.RepoPath(u.Name, repo.Name) - isExist, err := util.IsExist(repoPath) + isExist, err := gitrepo.IsRepositoryExist(ctx, repo) if err != nil { - log.Error("Unable to check if %s exists. Error: %v", repoPath, err) + log.Error("Unable to check if %s exists. Error: %v", repo.FullName(), err) return err } if isExist { @@ -270,15 +269,15 @@ func CreateRepositoryDirectly(ctx context.Context, doer, u *user_model.User, opt // // Previously Gitea would just delete and start afresh - this was naughty. // So we will now fail and delegate to other functionality to adopt or delete - log.Error("Files already exist in %s and we are not going to adopt or delete.", repoPath) + log.Error("Files already exist in %s and we are not going to adopt or delete.", repo.FullName()) return repo_model.ErrRepoFilesAlreadyExist{ Uname: u.Name, Name: repo.Name, } } - if err = initRepository(ctx, repoPath, doer, repo, opts); err != nil { - if err2 := util.RemoveAll(repoPath); err2 != nil { + if err = initRepository(ctx, doer, repo, opts); err != nil { + if err2 := util.RemoveAll(repo.RepoPath()); err2 != nil { log.Error("initRepository: %v", err) return fmt.Errorf( "delete repo directory %s/%s failed(2): %v", u.Name, repo.Name, err2) @@ -300,7 +299,7 @@ func CreateRepositoryDirectly(ctx context.Context, doer, u *user_model.User, opt } if stdout, _, err := git.NewCommand("update-server-info"). - RunStdString(ctx, &git.RunOpts{Dir: repoPath}); err != nil { + RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}); err != nil { log.Error("CreateRepository(git update-server-info) in %v: Stdout: %s\nError: %v", repo, stdout, err) rollbackRepo = repo rollbackRepo.OwnerID = u.ID @@ -312,7 +311,7 @@ func CreateRepositoryDirectly(ctx context.Context, doer, u *user_model.User, opt if len(opts.License) > 0 { licenses = append(licenses, opts.License) - stdout, _, err := git.NewCommand("rev-parse", "HEAD").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + stdout, _, err := git.NewCommand("rev-parse", "HEAD").RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}) if err != nil { log.Error("CreateRepository(git rev-parse HEAD) in %v: Stdout: %s\nError: %v", repo, stdout, err) rollbackRepo = repo @@ -353,14 +352,13 @@ func CreateRepositoryByExample(ctx context.Context, doer, u *user_model.User, re } } - repoPath := repo_model.RepoPath(u.Name, repo.Name) - isExist, err := util.IsExist(repoPath) + isExist, err := gitrepo.IsRepositoryExist(ctx, repo) if err != nil { - log.Error("Unable to check if %s exists. Error: %v", repoPath, err) + log.Error("Unable to check if %s exists. Error: %v", repo.FullName(), err) return err } if !overwriteOrAdopt && isExist { - log.Error("Files already exist in %s and we are not going to adopt or delete.", repoPath) + log.Error("Files already exist in %s and we are not going to adopt or delete.", repo.FullName()) return repo_model.ErrRepoFilesAlreadyExist{ Uname: u.Name, Name: repo.Name, diff --git a/services/repository/fork.go b/services/repository/fork.go index a79dc62ef1..1bd4d4a13b 100644 --- a/services/repository/fork.go +++ b/services/repository/fork.go @@ -110,15 +110,13 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork return } - repoPath := repo_model.RepoPath(owner.Name, repo.Name) - - if exists, _ := util.IsExist(repoPath); !exists { + if exists, _ := gitrepo.IsRepositoryExist(ctx, repo); !exists { return } // As the transaction will be failed and hence database changes will be destroyed we only need // to delete the related repository on the filesystem - if errDelete := util.RemoveAll(repoPath); errDelete != nil { + if errDelete := util.RemoveAll(repo.RepoPath()); errDelete != nil { log.Error("Failed to remove fork repo") } } diff --git a/services/repository/generate.go b/services/repository/generate.go index a47ab7db53..9d2bbb1f7f 100644 --- a/services/repository/generate.go +++ b/services/repository/generate.go @@ -258,7 +258,7 @@ func generateRepoCommit(ctx context.Context, repo, templateRepo, generateRepo *r func generateGitContent(ctx context.Context, repo, templateRepo, generateRepo *repo_model.Repository) (err error) { tmpDir, err := os.MkdirTemp(os.TempDir(), "gitea-"+repo.Name) if err != nil { - return fmt.Errorf("Failed to create temp dir for repository %s: %w", repo.RepoPath(), err) + return fmt.Errorf("Failed to create temp dir for repository %s: %w", repo.FullName(), err) } defer func() { @@ -350,10 +350,9 @@ func generateRepository(ctx context.Context, doer, owner *user_model.User, templ return nil, err } - repoPath := generateRepo.RepoPath() - isExist, err := util.IsExist(repoPath) + isExist, err := gitrepo.IsRepositoryExist(ctx, generateRepo) if err != nil { - log.Error("Unable to check if %s exists. Error: %v", repoPath, err) + log.Error("Unable to check if %s exists. Error: %v", generateRepo.FullName(), err) return nil, err } if isExist { @@ -363,7 +362,7 @@ func generateRepository(ctx context.Context, doer, owner *user_model.User, templ } } - if err = repo_module.CheckInitRepository(ctx, owner.Name, generateRepo.Name, generateRepo.ObjectFormatName); err != nil { + if err = repo_module.CheckInitRepository(ctx, generateRepo); err != nil { return generateRepo, err } @@ -372,7 +371,7 @@ func generateRepository(ctx context.Context, doer, owner *user_model.User, templ } if stdout, _, err := git.NewCommand("update-server-info"). - RunStdString(ctx, &git.RunOpts{Dir: repoPath}); err != nil { + RunStdString(ctx, &git.RunOpts{Dir: generateRepo.RepoPath()}); err != nil { log.Error("GenerateRepository(git update-server-info) in %v: Stdout: %s\nError: %v", generateRepo, stdout, err) return generateRepo, fmt.Errorf("error in GenerateRepository(git update-server-info): %w", err) }