diff --git a/cmd/admin.go b/cmd/admin.go index 6c9480e76eb7a..9b2eed34d233e 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()) + log.Trace("Synchronizing repo %s with path %s", repo.FullName(), gitrepo.RepoGitURL(repo)) gitRepo, err := gitrepo.OpenRepository(ctx, repo) if err != nil { log.Warn("OpenRepository: %v", err) diff --git a/models/git/commit_status.go b/models/git/commit_status.go index 0579a41209e76..18ed3ff6fb6c8 100644 --- a/models/git/commit_status.go +++ b/models/git/commit_status.go @@ -18,6 +18,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" api "code.gitea.io/gitea/modules/structs" @@ -453,9 +454,9 @@ func NewCommitStatus(ctx context.Context, opts NewCommitStatusOptions) error { return fmt.Errorf("NewCommitStatus[nil, %s]: no repository specified", opts.SHA) } - repoPath := opts.Repo.RepoPath() + repoURL := gitrepo.RepoGitURL(opts.Repo) if opts.Creator == nil { - return fmt.Errorf("NewCommitStatus[%s, %s]: no user specified", repoPath, opts.SHA) + return fmt.Errorf("NewCommitStatus[%s, %s]: no user specified", repoURL, opts.SHA) } ctx, committer, err := db.TxContext(ctx) @@ -477,13 +478,13 @@ func NewCommitStatus(ctx context.Context, opts NewCommitStatusOptions) error { opts.CommitStatus.CreatorID = opts.Creator.ID opts.CommitStatus.RepoID = opts.Repo.ID opts.CommitStatus.Index = idx - log.Debug("NewCommitStatus[%s, %s]: %d", repoPath, opts.SHA, opts.CommitStatus.Index) + log.Debug("NewCommitStatus[%s, %s]: %d", repoURL, opts.SHA, opts.CommitStatus.Index) opts.CommitStatus.ContextHash = hashCommitStatusContext(opts.CommitStatus.Context) // Insert new CommitStatus if _, err = db.GetEngine(ctx).Insert(opts.CommitStatus); err != nil { - return fmt.Errorf("insert CommitStatus[%s, %s]: %w", repoPath, opts.SHA, err) + return fmt.Errorf("insert CommitStatus[%s, %s]: %w", repoURL, opts.SHA, err) } return committer.Commit() diff --git a/modules/git/git.go b/modules/git/git.go index 05ca260855535..98e094bd63df2 100644 --- a/modules/git/git.go +++ b/modules/git/git.go @@ -392,8 +392,3 @@ func configUnsetAll(key, value string) error { } return fmt.Errorf("failed to get git config %s, err: %w", key, err) } - -// Fsck verifies the connectivity and validity of the objects in the database -func Fsck(ctx context.Context, repoPath string, timeout time.Duration, args TrustedCmdArgs) error { - return NewCommand(ctx, "fsck").AddArguments(args...).Run(&RunOpts{Timeout: timeout, Dir: repoPath}) -} diff --git a/modules/git/repo_branch.go b/modules/git/repo_branch.go index 552ae2bb8c6c1..12f88feb9a05e 100644 --- a/modules/git/repo_branch.go +++ b/modules/git/repo_branch.go @@ -14,17 +14,6 @@ import ( // BranchPrefix base dir of the branch information file store on git const BranchPrefix = "refs/heads/" -// IsReferenceExist returns true if given reference exists in the repository. -func IsReferenceExist(ctx context.Context, repoPath, name string) bool { - _, _, err := NewCommand(ctx, "show-ref", "--verify").AddDashesAndList(name).RunStdString(&RunOpts{Dir: repoPath}) - return err == nil -} - -// IsBranchExist returns true if given branch exists in the repository. -func IsBranchExist(ctx context.Context, repoPath, name string) bool { - return IsReferenceExist(ctx, repoPath, BranchPrefix+name) -} - // Branch represents a Git branch. type Branch struct { Name string diff --git a/modules/git/repo_tag.go b/modules/git/repo_tag.go index 2026a4c9f5c1a..818ac8c95c9fb 100644 --- a/modules/git/repo_tag.go +++ b/modules/git/repo_tag.go @@ -5,7 +5,6 @@ package git import ( - "context" "fmt" "io" "strings" @@ -17,11 +16,6 @@ import ( // TagPrefix tags prefix path on the repository const TagPrefix = "refs/tags/" -// IsTagExist returns true if given tag exists in the repository. -func IsTagExist(ctx context.Context, repoPath, name string) bool { - return IsReferenceExist(ctx, repoPath, TagPrefix+name) -} - // CreateTag create one tag in the repository func (repo *Repository) CreateTag(name, revision string) error { _, _, err := NewCommand(repo.Ctx, "tag").AddDashesAndList(name, revision).RunStdString(&RunOpts{Dir: repo.Path}) diff --git a/modules/gitrepo/branch.go b/modules/gitrepo/branch.go index e13a4c82e1c25..bb79fb95cac7a 100644 --- a/modules/gitrepo/branch.go +++ b/modules/gitrepo/branch.go @@ -31,6 +31,26 @@ func GetBranchCommitID(ctx context.Context, repo Repository, branch string) (str return gitRepo.GetBranchCommitID(branch) } +// IsReferenceExist returns true if given reference exists in the repository. +func IsReferenceExist(ctx context.Context, repo Repository, name string) bool { + _, _, err := git.NewCommand(ctx, "show-ref", "--verify").AddDashesAndList(name).RunStdString(&git.RunOpts{Dir: repoPath(repo)}) + return err == nil +} + +func IsWikiReferenceExist(ctx context.Context, repo Repository, name string) bool { + _, _, err := git.NewCommand(ctx, "show-ref", "--verify").AddDashesAndList(name).RunStdString(&git.RunOpts{Dir: wikiPath(repo)}) + return err == nil +} + +// IsBranchExist returns true if given branch exists in the repository. +func IsBranchExist(ctx context.Context, repo Repository, name string) bool { + return IsReferenceExist(ctx, repo, git.BranchPrefix+name) +} + +func IsWikiBranchExist(ctx context.Context, repo Repository, name string) bool { + return IsWikiReferenceExist(ctx, repo, git.BranchPrefix+name) +} + // SetDefaultBranch sets default branch of repository. func SetDefaultBranch(ctx context.Context, repo Repository, name string) error { _, _, err := git.NewCommand(ctx, "symbolic-ref", "HEAD"). diff --git a/modules/gitrepo/format.go b/modules/gitrepo/format.go new file mode 100644 index 0000000000000..4f0888b4f1f0d --- /dev/null +++ b/modules/gitrepo/format.go @@ -0,0 +1,38 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package gitrepo + +import ( + "context" + "errors" + "strings" + + "code.gitea.io/gitea/modules/git" +) + +// GetObjectFormatOfRepo returns the hash type of repository at a given path +func GetObjectFormatOfRepo(ctx context.Context, repo Repository) (git.ObjectFormat, error) { + var stdout, stderr strings.Builder + + err := git.NewCommand(ctx, "hash-object", "--stdin").Run(&git.RunOpts{ + Dir: repoPath(repo), + Stdout: &stdout, + Stderr: &stderr, + Stdin: &strings.Reader{}, + }) + if err != nil { + return nil, err + } + + if stderr.Len() > 0 { + return nil, errors.New(stderr.String()) + } + + h, err := git.NewIDFromString(strings.TrimRight(stdout.String(), "\n")) + if err != nil { + return nil, err + } + + return h.Type(), nil +} diff --git a/modules/gitrepo/fsck.go b/modules/gitrepo/fsck.go new file mode 100644 index 0000000000000..d1e059a1d8121 --- /dev/null +++ b/modules/gitrepo/fsck.go @@ -0,0 +1,16 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package gitrepo + +import ( + "context" + "time" + + "code.gitea.io/gitea/modules/git" +) + +// Fsck verifies the connectivity and validity of the objects in the database +func Fsck(ctx context.Context, repo Repository, timeout time.Duration, args git.TrustedCmdArgs) error { + return git.NewCommand(ctx, "fsck").AddArguments(args...).Run(&git.RunOpts{Timeout: timeout, Dir: repoPath(repo)}) +} diff --git a/modules/gitrepo/gitrepo.go b/modules/gitrepo/gitrepo.go index d89f8f9c0c88c..fcaeddb08cb18 100644 --- a/modules/gitrepo/gitrepo.go +++ b/modules/gitrepo/gitrepo.go @@ -5,12 +5,16 @@ package gitrepo import ( "context" + "fmt" "io" "path/filepath" "strings" + "time" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/util" ) type Repository interface { @@ -18,6 +22,10 @@ type Repository interface { GetOwnerName() string } +func fullName(repo Repository) string { + return repo.GetOwnerName() + "/" + repo.GetName() +} + func repoPath(repo Repository) string { return filepath.Join(setting.RepoRootPath, strings.ToLower(repo.GetOwnerName()), strings.ToLower(repo.GetName())+".git") } @@ -101,3 +109,42 @@ func RepositoryFromContextOrOpenPath(ctx context.Context, path string) (*git.Rep gitRepo, err := git.OpenRepository(ctx, path) return gitRepo, gitRepo, err } + +func IsRepositoryExist(ctx context.Context, repo Repository) (bool, error) { + return util.IsExist(repoPath(repo)) +} + +func RenameRepository(ctx context.Context, repo Repository, newName string) error { + newRepoPath := filepath.Join(setting.RepoRootPath, strings.ToLower(repo.GetOwnerName()), strings.ToLower(newName)+".git") + if err := util.Rename(repoPath(repo), newRepoPath); err != nil { + return fmt.Errorf("rename repository directory: %w", err) + } + return nil +} + +func RenameWikiRepository(ctx context.Context, repo Repository, newName string) error { + newWikiRepoPath := filepath.Join(setting.RepoRootPath, strings.ToLower(repo.GetOwnerName()), strings.ToLower(newName)+".wiki.git") + if err := util.Rename(wikiPath(repo), newWikiRepoPath); err != nil { + return fmt.Errorf("rename repository wiki directory: %w", err) + } + return nil +} + +func DeleteRepository(ctx context.Context, repo Repository) error { + return util.RemoveAll(repoPath(repo)) +} + +func ForkRepository(ctx context.Context, baseRepo, targetRepo Repository, singleBranch string) error { + cloneCmd := git.NewCommand(ctx, "clone", "--bare") + if singleBranch != "" { + cloneCmd.AddArguments("--single-branch", "--branch").AddDynamicArguments(singleBranch) + } + + if stdout, _, err := cloneCmd.AddDynamicArguments(repoPath(baseRepo), repoPath(targetRepo)). + SetDescription(fmt.Sprintf("ForkRepository(git clone): %s to %s", fullName(baseRepo), fullName(targetRepo))). + RunStdBytes(&git.RunOpts{Timeout: 10 * time.Minute}); err != nil { + log.Error("Fork Repository (git clone) Failed for %v (from %v):\nStdout: %s\nError: %v", targetRepo, baseRepo, stdout, err) + return fmt.Errorf("git clone: %w", err) + } + return nil +} diff --git a/modules/repository/hooks.go b/modules/gitrepo/hooks.go similarity index 93% rename from modules/repository/hooks.go rename to modules/gitrepo/hooks.go index 95849789ab1f9..5239fa4384987 100644 --- a/modules/repository/hooks.go +++ b/modules/gitrepo/hooks.go @@ -1,9 +1,10 @@ // Copyright 2020 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT -package repository +package gitrepo import ( + "context" "fmt" "os" "path/filepath" @@ -106,9 +107,14 @@ done } // CreateDelegateHooks creates all the hooks scripts for the repo -func CreateDelegateHooks(repoPath string) (err error) { +func CreateDelegateHooks(ctx context.Context, repo Repository, iswiki bool) (err error) { hookNames, hookTpls, giteaHookTpls := getHookTemplates() - hookDir := filepath.Join(repoPath, "hooks") + var hookDir string + if iswiki { + hookDir = filepath.Join(wikiPath(repo), "hooks") + } else { + hookDir = filepath.Join(repoPath(repo), "hooks") + } for i, hookName := range hookNames { oldHookPath := filepath.Join(hookDir, hookName) @@ -170,10 +176,15 @@ func ensureExecutable(filename string) error { } // CheckDelegateHooks checks the hooks scripts for the repo -func CheckDelegateHooks(repoPath string) ([]string, error) { +func CheckDelegateHooks(ctx context.Context, repo Repository, isWiki bool) ([]string, error) { hookNames, hookTpls, giteaHookTpls := getHookTemplates() - hookDir := filepath.Join(repoPath, "hooks") + var hookDir string + if isWiki { + hookDir = filepath.Join(wikiPath(repo), "hooks") + } else { + hookDir = filepath.Join(repoPath(repo), "hooks") + } results := make([]string, 0, 10) for i, hookName := range hookNames { diff --git a/modules/gitrepo/stats.go b/modules/gitrepo/stats.go new file mode 100644 index 0000000000000..b0d2c8f394768 --- /dev/null +++ b/modules/gitrepo/stats.go @@ -0,0 +1,19 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package gitrepo + +import ( + "context" + + "code.gitea.io/gitea/modules/git" +) + +// CountDivergingCommits determines how many commits a branch is ahead or behind the repository's base branch +func CountDivergingCommits(ctx context.Context, repo Repository, baseBranch, branch string) (*git.DivergeObject, error) { + divergence, err := git.GetDivergingCommits(ctx, repoPath(repo), baseBranch, branch) + if err != nil { + return nil, err + } + return &divergence, nil +} diff --git a/modules/gitrepo/tag.go b/modules/gitrepo/tag.go new file mode 100644 index 0000000000000..5c1625c0576a1 --- /dev/null +++ b/modules/gitrepo/tag.go @@ -0,0 +1,15 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package gitrepo + +import ( + "context" + + "code.gitea.io/gitea/modules/git" +) + +// IsTagExist returns true if given tag exists in the repository. +func IsTagExist(ctx context.Context, repo Repository, name string) bool { + return IsReferenceExist(ctx, repo, git.TagPrefix+name) +} diff --git a/modules/gitrepo/url.go b/modules/gitrepo/url.go index b355d0fa93aac..83899c3f8775e 100644 --- a/modules/gitrepo/url.go +++ b/modules/gitrepo/url.go @@ -6,3 +6,7 @@ package gitrepo func RepoGitURL(repo Repository) string { return repoPath(repo) } + +func WikiRepoGitURL(repo Repository) string { + return repoPath(repo) +} diff --git a/modules/gitrepo/user.go b/modules/gitrepo/user.go new file mode 100644 index 0000000000000..1da9e6883e9d3 --- /dev/null +++ b/modules/gitrepo/user.go @@ -0,0 +1,17 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package gitrepo + +import ( + "context" + "path/filepath" + "strings" + + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/util" +) + +func RenameDir(ctx context.Context, oldName, newName string) error { + return util.Rename(filepath.Join(setting.RepoRootPath, strings.ToLower(oldName)), filepath.Join(setting.RepoRootPath, strings.ToLower(newName))) +} diff --git a/modules/indexer/stats/db.go b/modules/indexer/stats/db.go index 98a977c7008fe..fd9dbdce6ff46 100644 --- a/modules/indexer/stats/db.go +++ b/modules/indexer/stats/db.go @@ -49,10 +49,10 @@ func (db *DBIndexer) Index(id int64) error { commitID, err := gitRepo.GetBranchCommitID(repo.DefaultBranch) if err != nil { if git.IsErrBranchNotExist(err) || git.IsErrNotExist(err) || setting.IsInTesting { - log.Debug("Unable to get commit ID for default branch %s in %s ... skipping this repository", repo.DefaultBranch, repo.RepoPath()) + log.Debug("Unable to get commit ID for default branch %s in %s ... skipping this repository", repo.DefaultBranch, gitrepo.RepoGitURL(repo)) return nil } - log.Error("Unable to get commit ID for default branch %s in %s. Error: %v", repo.DefaultBranch, repo.RepoPath(), err) + log.Error("Unable to get commit ID for default branch %s in %s. Error: %v", repo.DefaultBranch, gitrepo.RepoGitURL(repo), err) return err } @@ -65,17 +65,17 @@ func (db *DBIndexer) Index(id int64) error { stats, err := gitRepo.GetLanguageStats(commitID) if err != nil { if !setting.IsInTesting { - log.Error("Unable to get language stats for ID %s for default branch %s in %s. Error: %v", commitID, repo.DefaultBranch, repo.RepoPath(), err) + log.Error("Unable to get language stats for ID %s for default branch %s in %s. Error: %v", commitID, repo.DefaultBranch, gitrepo.RepoGitURL(repo), err) } return err } err = repo_model.UpdateLanguageStats(ctx, repo, commitID, stats) if err != nil { - log.Error("Unable to update language stats for ID %s for default branch %s in %s. Error: %v", commitID, repo.DefaultBranch, repo.RepoPath(), err) + log.Error("Unable to update language stats for ID %s for default branch %s in %s. Error: %v", commitID, repo.DefaultBranch, gitrepo.RepoGitURL(repo), err) return err } - log.Debug("DBIndexer completed language stats for ID %s for default branch %s in %s. stats count: %d", commitID, repo.DefaultBranch, repo.RepoPath(), len(stats)) + log.Debug("DBIndexer completed language stats for ID %s for default branch %s in %s. stats count: %d", commitID, repo.DefaultBranch, gitrepo.RepoGitURL(repo), len(stats)) return nil } diff --git a/modules/migration/pullrequest.go b/modules/migration/pullrequest.go index 4e7500f0d67f8..1435991bd2a8b 100644 --- a/modules/migration/pullrequest.go +++ b/modules/migration/pullrequest.go @@ -45,7 +45,7 @@ func (p *PullRequest) GetContext() DownloaderContext { return p.Context } // IsForkPullRequest returns true if the pull request from a forked repository but not the same repository func (p *PullRequest) IsForkPullRequest() bool { - return p.Head.RepoPath() != p.Base.RepoPath() + return p.Head.RepoFullName() != p.Base.RepoFullName() } // GetGitRefName returns pull request relative path to head @@ -62,8 +62,8 @@ type PullRequestBranch struct { OwnerName string `yaml:"owner_name"` } -// RepoPath returns pull request repo path -func (p PullRequestBranch) RepoPath() string { +// RepoFullName returns pull request repo full name +func (p PullRequestBranch) RepoFullName() string { return fmt.Sprintf("%s/%s", p.OwnerName, p.RepoName) } diff --git a/modules/repository/commits.go b/modules/repository/commits.go index ede60429a13fb..a39642fe376b3 100644 --- a/modules/repository/commits.go +++ b/modules/repository/commits.go @@ -10,6 +10,7 @@ import ( "time" "code.gitea.io/gitea/models/avatars" + repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/git" @@ -43,7 +44,7 @@ func NewPushCommits() *PushCommits { } // toAPIPayloadCommit converts a single PushCommit to an api.PayloadCommit object. -func (pc *PushCommits) toAPIPayloadCommit(ctx context.Context, emailUsers map[string]*user_model.User, repoPath, repoLink string, commit *PushCommit) (*api.PayloadCommit, error) { +func (pc *PushCommits) toAPIPayloadCommit(ctx context.Context, emailUsers map[string]*user_model.User, repo *repo_model.Repository, repoLink string, commit *PushCommit) (*api.PayloadCommit, error) { var err error authorUsername := "" author, ok := emailUsers[commit.AuthorEmail] @@ -70,7 +71,7 @@ func (pc *PushCommits) toAPIPayloadCommit(ctx context.Context, emailUsers map[st committerUsername = committer.Name } - fileStatus, err := git.GetCommitFileStatus(ctx, repoPath, commit.Sha1) + fileStatus, err := git.GetCommitFileStatus(ctx, repo.RepoPath(), commit.Sha1) if err != nil { return nil, fmt.Errorf("FileStatus [commit_sha1: %s]: %w", commit.Sha1, err) } @@ -98,14 +99,14 @@ func (pc *PushCommits) toAPIPayloadCommit(ctx context.Context, emailUsers map[st // ToAPIPayloadCommits converts a PushCommits object to api.PayloadCommit format. // It returns all converted commits and, if provided, the head commit or an error otherwise. -func (pc *PushCommits) ToAPIPayloadCommits(ctx context.Context, repoPath, repoLink string) ([]*api.PayloadCommit, *api.PayloadCommit, error) { +func (pc *PushCommits) ToAPIPayloadCommits(ctx context.Context, repo *repo_model.Repository, repoLink string) ([]*api.PayloadCommit, *api.PayloadCommit, error) { commits := make([]*api.PayloadCommit, len(pc.Commits)) var headCommit *api.PayloadCommit emailUsers := make(map[string]*user_model.User) for i, commit := range pc.Commits { - apiCommit, err := pc.toAPIPayloadCommit(ctx, emailUsers, repoPath, repoLink, commit) + apiCommit, err := pc.toAPIPayloadCommit(ctx, emailUsers, repo, repoLink, commit) if err != nil { return nil, nil, err } @@ -117,7 +118,7 @@ func (pc *PushCommits) ToAPIPayloadCommits(ctx context.Context, repoPath, repoLi } if pc.HeadCommit != nil && headCommit == nil { var err error - headCommit, err = pc.toAPIPayloadCommit(ctx, emailUsers, repoPath, repoLink, pc.HeadCommit) + headCommit, err = pc.toAPIPayloadCommit(ctx, emailUsers, repo, repoLink, pc.HeadCommit) if err != nil { return nil, nil, err } diff --git a/modules/repository/commits_test.go b/modules/repository/commits_test.go index 248673a907d47..228c2057bb3cf 100644 --- a/modules/repository/commits_test.go +++ b/modules/repository/commits_test.go @@ -52,7 +52,7 @@ func TestPushCommits_ToAPIPayloadCommits(t *testing.T) { pushCommits.HeadCommit = &PushCommit{Sha1: "69554a6"} repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 16}) - payloadCommits, headCommit, err := pushCommits.ToAPIPayloadCommits(git.DefaultContext, repo.RepoPath(), "/user2/repo16") + payloadCommits, headCommit, err := pushCommits.ToAPIPayloadCommits(git.DefaultContext, repo, "/user2/repo16") assert.NoError(t, err) assert.Len(t, payloadCommits, 3) assert.NotNil(t, headCommit) diff --git a/modules/repository/init.go b/modules/repository/init.go index 5f500c5233faa..57141d5ec7b8a 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, objectFormatName string) (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.RepoPath(), 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, objectFormatName); err != nil { return fmt.Errorf("git.InitRepository: %w", err) - } else if err = CreateDelegateHooks(repoPath); err != nil { + } else if err = gitrepo.CreateDelegateHooks(ctx, repo, false); err != nil { return fmt.Errorf("createDelegateHooks: %w", err) } return nil diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index 63de4b8b6a2be..ddc1b942e0a50 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -527,7 +527,7 @@ func CreateBranchProtection(ctx *context.APIContext) { isPlainRule := !git_model.IsRuleNameSpecial(ruleName) var isBranchExist bool if isPlainRule { - isBranchExist = git.IsBranchExist(ctx.Req.Context(), ctx.Repo.Repository.RepoPath(), ruleName) + isBranchExist = gitrepo.IsBranchExist(ctx.Req.Context(), ctx.Repo.Repository, ruleName) } protectBranch, err := git_model.GetProtectedBranchRuleByName(ctx, repo.ID, ruleName) @@ -980,7 +980,7 @@ func EditBranchProtection(ctx *context.APIContext) { isPlainRule := !git_model.IsRuleNameSpecial(bpName) var isBranchExist bool if isPlainRule { - isBranchExist = git.IsBranchExist(ctx.Req.Context(), ctx.Repo.Repository.RepoPath(), bpName) + isBranchExist = gitrepo.IsBranchExist(ctx.Req.Context(), ctx.Repo.Repository, bpName) } if isBranchExist { diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 856e2f7392bae..208e37fe6d77d 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -34,6 +34,7 @@ import ( "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/emoji" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/gitrepo" issue_indexer "code.gitea.io/gitea/modules/indexer/issues" issue_template "code.gitea.io/gitea/modules/issue/template" "code.gitea.io/gitea/modules/log" @@ -1960,7 +1961,7 @@ func ViewIssue(ctx *context.Context) { isPullBranchDeletable := canDelete && pull.HeadRepo != nil && - git.IsBranchExist(ctx, pull.HeadRepo.RepoPath(), pull.HeadBranch) && + gitrepo.IsBranchExist(ctx, pull.HeadRepo, pull.HeadBranch) && (!pull.HasMerged || ctx.Data["HeadBranchCommitID"] == ctx.Data["PullHeadCommitID"]) if isPullBranchDeletable && pull.HasMerged { @@ -3074,7 +3075,7 @@ func NewComment(ctx *context.Context) { ctx.ServerError("Unable to load head repo", err) return } - if ok := git.IsBranchExist(ctx, pull.HeadRepo.RepoPath(), pull.BaseBranch); !ok { + if ok := gitrepo.IsBranchExist(ctx, pull.HeadRepo, pull.BaseBranch); !ok { // todo localize ctx.JSONError("The origin branch is delete, cannot reopen.") return diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index e001e872aa8af..7344d63a31bf0 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -392,7 +392,7 @@ func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.C if pull.Flow == issues_model.PullRequestFlowGithub { headBranchExist = headGitRepo.IsBranchExist(pull.HeadBranch) } else { - headBranchExist = git.IsReferenceExist(ctx, baseGitRepo.Path, pull.GetGitRefName()) + headBranchExist = gitrepo.IsReferenceExist(ctx, pull.BaseRepo, pull.GetGitRefName()) } if headBranchExist { diff --git a/services/actions/notifier.go b/services/actions/notifier.go index a4ebdf9e888ee..77f879e8ce753 100644 --- a/services/actions/notifier.go +++ b/services/actions/notifier.go @@ -524,7 +524,7 @@ func (n *actionsNotifier) PushCommits(ctx context.Context, pusher *user_model.Us ctx = withMethod(ctx, "PushCommits") apiPusher := convert.ToUser(ctx, pusher, nil) - apiCommits, apiHeadCommit, err := commits.ToAPIPayloadCommits(ctx, repo.RepoPath(), repo.HTMLURL()) + apiCommits, apiHeadCommit, err := commits.ToAPIPayloadCommits(ctx, repo, repo.HTMLURL()) if err != nil { log.Error("commits.ToAPIPayloadCommits failed: %v", err) return @@ -585,7 +585,7 @@ func (n *actionsNotifier) SyncPushCommits(ctx context.Context, pusher *user_mode ctx = withMethod(ctx, "SyncPushCommits") apiPusher := convert.ToUser(ctx, pusher, nil) - apiCommits, apiHeadCommit, err := commits.ToAPIPayloadCommits(ctx, repo.RepoPath(), repo.HTMLURL()) + apiCommits, apiHeadCommit, err := commits.ToAPIPayloadCommits(ctx, repo, repo.HTMLURL()) if err != nil { log.Error("commits.ToAPIPayloadCommits failed: %v", err) return diff --git a/services/automerge/automerge.go b/services/automerge/automerge.go index ed7a0141b9f3d..46f1d55bbc0c6 100644 --- a/services/automerge/automerge.go +++ b/services/automerge/automerge.go @@ -253,7 +253,7 @@ func handlePullRequestAutoMerge(pullID int64, sha string) { return } case issues_model.PullRequestFlowAGit: - headBranchExist := git.IsReferenceExist(ctx, baseGitRepo.Path, pr.GetGitRefName()) + headBranchExist := baseGitRepo.IsReferenceExist(pr.GetGitRefName()) if !headBranchExist { log.Warn("Head branch of auto merge %-v does not exist [HeadRepoID: %d, Branch(Agit): %s]", pr, pr.HeadRepoID, pr.HeadBranch) return diff --git a/services/doctor/misc.go b/services/doctor/misc.go index 9300c3a25c9c6..08cd71dce3145 100644 --- a/services/doctor/misc.go +++ b/services/doctor/misc.go @@ -18,7 +18,6 @@ import ( "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" - "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" @@ -50,14 +49,14 @@ func checkScriptType(ctx context.Context, logger log.Logger, autofix bool) error func checkHooks(ctx context.Context, logger log.Logger, autofix bool) error { if err := iterateRepositories(ctx, func(repo *repo_model.Repository) error { - results, err := repository.CheckDelegateHooks(repo.RepoPath()) + results, err := gitrepo.CheckDelegateHooks(ctx, repo, false) if err != nil { logger.Critical("Unable to check delegate hooks for repo %-v. ERROR: %v", repo, err) return fmt.Errorf("Unable to check delegate hooks for repo %-v. ERROR: %w", repo, err) } if len(results) > 0 && autofix { - logger.Warn("Regenerated hooks for %s", repo.FullName()) - if err := repository.CreateDelegateHooks(repo.RepoPath()); err != nil { + logger.Warn("Regenerated hooks for %s", gitrepo.RepoGitURL(repo)) + if err := gitrepo.CreateDelegateHooks(ctx, repo, false); err != nil { logger.Critical("Unable to recreate delegate hooks for %-v. ERROR: %v", repo, err) return fmt.Errorf("Unable to recreate delegate hooks for %-v. ERROR: %w", repo, err) } diff --git a/services/pull/commit_status.go b/services/pull/commit_status.go index aa1ad7cd665b8..c4b4709fe327d 100644 --- a/services/pull/commit_status.go +++ b/services/pull/commit_status.go @@ -10,7 +10,6 @@ import ( "code.gitea.io/gitea/models/db" 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" @@ -134,7 +133,7 @@ func GetPullRequestCommitStatusState(ctx context.Context, pr *issues_model.PullR if pr.Flow == issues_model.PullRequestFlowGithub && !headGitRepo.IsBranchExist(pr.HeadBranch) { return "", errors.New("Head branch does not exist, can not merge") } - if pr.Flow == issues_model.PullRequestFlowAGit && !git.IsReferenceExist(ctx, headGitRepo.Path, pr.GetGitRefName()) { + if pr.Flow == issues_model.PullRequestFlowAGit && !gitrepo.IsReferenceExist(ctx, pr.HeadRepo, pr.GetGitRefName()) { return "", errors.New("Head branch does not exist, can not merge") } diff --git a/services/pull/pull.go b/services/pull/pull.go index e69c842a2d4b5..a602f6ce96f43 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -415,7 +415,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string, for _, pr := range prs { divergence, err := GetDiverging(ctx, pr) if err != nil { - if git_model.IsErrBranchNotExist(err) && !git.IsBranchExist(ctx, pr.HeadRepo.RepoPath(), pr.HeadBranch) { + if git_model.IsErrBranchNotExist(err) && !gitrepo.IsBranchExist(ctx, pr.HeadRepo, pr.HeadBranch) { log.Warn("Cannot test PR %s/%d: head_branch %s no longer exists", pr.BaseRepo.Name, pr.IssueID, pr.HeadBranch) } else { log.Error("GetDiverging: %v", err) diff --git a/services/pull/temp_repo.go b/services/pull/temp_repo.go index e5753178b8981..8d8b42513a09a 100644 --- a/services/pull/temp_repo.go +++ b/services/pull/temp_repo.go @@ -15,6 +15,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/log" repo_module "code.gitea.io/gitea/modules/repository" ) @@ -181,7 +182,7 @@ func createTemporaryRepoForPR(ctx context.Context, pr *issues_model.PullRequest) if err := git.NewCommand(ctx, "fetch").AddArguments(fetchArgs...).AddDynamicArguments(remoteRepoName, headBranch+":"+trackingBranch). Run(prCtx.RunOpts()); err != nil { cancel() - if !git.IsBranchExist(ctx, pr.HeadRepo.RepoPath(), pr.HeadBranch) { + if !gitrepo.IsBranchExist(ctx, pr.HeadRepo, pr.HeadBranch) { return nil, nil, git_model.ErrBranchNotExist{ BranchName: pr.HeadBranch, } diff --git a/services/repository/adopt.go b/services/repository/adopt.go index 3d6fe71a09191..d7667ee71b24b 100644 --- a/services/repository/adopt.go +++ b/services/repository/adopt.go @@ -110,14 +110,14 @@ func AdoptRepository(ctx context.Context, doer, u *user_model.User, opts CreateR func adoptRepository(ctx context.Context, repoPath string, repo *repo_model.Repository, defaultBranch string) (err error) { isExist, err := util.IsExist(repoPath) 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", gitrepo.RepoGitURL(repo), 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", gitrepo.RepoGitURL(repo)) } - if err := repo_module.CreateDelegateHooks(repoPath); err != nil { + if err := gitrepo.CreateDelegateHooks(ctx, repo, false); err != nil { return fmt.Errorf("createDelegateHooks: %w", err) } diff --git a/services/repository/check.go b/services/repository/check.go index 5cdcc146797c9..f5bc4e5ee1acf 100644 --- a/services/repository/check.go +++ b/services/repository/check.go @@ -14,6 +14,7 @@ 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/util" @@ -48,8 +49,7 @@ func GitFsckRepos(ctx context.Context, timeout time.Duration, args git.TrustedCm // GitFsckRepo calls 'git fsck' to check an individual repository's health. func GitFsckRepo(ctx context.Context, repo *repo_model.Repository, timeout time.Duration, args git.TrustedCmdArgs) error { log.Trace("Running health check on repository %-v", repo) - repoPath := repo.RepoPath() - if err := git.Fsck(ctx, repoPath, timeout, args); err != nil { + if err := gitrepo.Fsck(ctx, repo, timeout, args); err != nil { log.Warn("Failed to health check repository (%-v): %v", repo, err) if err = system_model.CreateRepositoryNotice("Failed to health check repository (%s): %v", repo.FullName(), err); err != nil { log.Error("CreateRepositoryNotice: %v", err) diff --git a/services/repository/create.go b/services/repository/create.go index 971793bcc6e35..c3743cacba9ab 100644 --- a/services/repository/create.go +++ b/services/repository/create.go @@ -47,7 +47,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() @@ -61,6 +61,7 @@ func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir, "GIT_COMMITTER_DATE="+commitTimeStr, ) + repoPath := repo.RepoPath() // Clone to temporary path and do the init commit. if stdout, _, err := git.NewCommand(ctx, "clone").AddDynamicArguments(repoPath, tmpDir). SetDescription(fmt.Sprintf("prepareRepoCommit (git clone): %s to %s", repoPath, tmpDir)). @@ -135,8 +136,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, opts.ObjectFormatName); err != nil { return err } @@ -144,7 +145,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", gitrepo.RepoGitURL(repo), err) } defer func() { if err := util.RemoveAll(tmpDir); err != nil { @@ -152,7 +153,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) } @@ -252,10 +253,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", gitrepo.RepoGitURL(repo), err) return err } if isExist { @@ -266,15 +266,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.", gitrepo.RepoGitURL(repo)) 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 := gitrepo.DeleteRepository(ctx, repo); err2 != nil { log.Error("initRepository: %v", err) return fmt.Errorf( "delete repo directory %s/%s failed(2): %v", u.Name, repo.Name, err2) @@ -296,8 +296,8 @@ func CreateRepositoryDirectly(ctx context.Context, doer, u *user_model.User, opt } if stdout, _, err := git.NewCommand(ctx, "update-server-info"). - SetDescription(fmt.Sprintf("CreateRepository(git update-server-info): %s", repoPath)). - RunStdString(&git.RunOpts{Dir: repoPath}); err != nil { + SetDescription(fmt.Sprintf("CreateRepository(git update-server-info): %s", gitrepo.RepoGitURL(repo))). + RunStdString(&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 diff --git a/services/repository/delete.go b/services/repository/delete.go index cd779b05c3501..729eadab1c157 100644 --- a/services/repository/delete.go +++ b/services/repository/delete.go @@ -24,6 +24,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/models/webhook" actions_module "code.gitea.io/gitea/modules/actions" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/storage" @@ -288,12 +289,11 @@ func DeleteRepositoryDirectly(ctx context.Context, doer *user_model.User, repoID // we delete the file but the database rollback, the repository will be broken. // Remove repository files. - repoPath := repo.RepoPath() - system_model.RemoveAllWithNotice(ctx, "Delete repository files", repoPath) + system_model.RemoveAllWithNotice(ctx, "Delete repository files", gitrepo.RepoGitURL(repo)) // Remove wiki files if repo.HasWiki() { - system_model.RemoveAllWithNotice(ctx, "Delete repository wiki", repo.WikiPath()) + system_model.RemoveAllWithNotice(ctx, "Delete repository wiki", gitrepo.WikiRepoGitURL(repo)) } // Remove archives diff --git a/services/repository/fork.go b/services/repository/fork.go index f074fd1082118..6b1e16b1c3486 100644 --- a/services/repository/fork.go +++ b/services/repository/fork.go @@ -7,7 +7,6 @@ import ( "context" "fmt" "strings" - "time" "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" @@ -99,23 +98,19 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork ObjectFormatName: opts.BaseRepo.ObjectFormatName, } - oldRepoPath := opts.BaseRepo.RepoPath() - needsRollback := false rollbackFn := func() { if !needsRollback { 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 := gitrepo.DeleteRepository(ctx, repo); errDelete != nil { log.Error("Failed to remove fork repo") } } @@ -149,16 +144,8 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork needsRollback = true - cloneCmd := git.NewCommand(txCtx, "clone", "--bare") - if opts.SingleBranch != "" { - cloneCmd.AddArguments("--single-branch", "--branch").AddDynamicArguments(opts.SingleBranch) - } - repoPath := repo_model.RepoPath(owner.Name, repo.Name) - if stdout, _, err := cloneCmd.AddDynamicArguments(oldRepoPath, repoPath). - SetDescription(fmt.Sprintf("ForkRepository(git clone): %s to %s", opts.BaseRepo.FullName(), repo.FullName())). - RunStdBytes(&git.RunOpts{Timeout: 10 * time.Minute}); err != nil { - log.Error("Fork Repository (git clone) Failed for %v (from %v):\nStdout: %s\nError: %v", repo, opts.BaseRepo, stdout, err) - return fmt.Errorf("git clone: %w", err) + if err := gitrepo.ForkRepository(txCtx, opts.BaseRepo, repo, opts.SingleBranch); err != nil { + return err } if err := repo_module.CheckDaemonExportOK(txCtx, repo); err != nil { @@ -167,12 +154,12 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork if stdout, _, err := git.NewCommand(txCtx, "update-server-info"). SetDescription(fmt.Sprintf("ForkRepository(git update-server-info): %s", repo.FullName())). - RunStdString(&git.RunOpts{Dir: repoPath}); err != nil { + RunStdString(&git.RunOpts{Dir: repo.RepoPath()}); err != nil { log.Error("Fork Repository (git update-server-info) failed for %v:\nStdout: %s\nError: %v", repo, stdout, err) return fmt.Errorf("git update-server-info: %w", err) } - if err = repo_module.CreateDelegateHooks(repoPath); err != nil { + if err = gitrepo.CreateDelegateHooks(ctx, repo, false); err != nil { return fmt.Errorf("createDelegateHooks: %w", err) } diff --git a/services/repository/generate.go b/services/repository/generate.go index 2b95bbcd4d315..ce74c91e89819 100644 --- a/services/repository/generate.go +++ b/services/repository/generate.go @@ -360,7 +360,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, generateRepo.ObjectFormatName); err != nil { return generateRepo, err } diff --git a/services/repository/hooks.go b/services/repository/hooks.go index 97e9e290a3e3d..97631124b4f6a 100644 --- a/services/repository/hooks.go +++ b/services/repository/hooks.go @@ -12,7 +12,6 @@ import ( "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" "xorm.io/builder" ) @@ -32,11 +31,11 @@ func SyncRepositoryHooks(ctx context.Context) error { default: } - if err := repo_module.CreateDelegateHooks(repo.RepoPath()); err != nil { + if err := gitrepo.CreateDelegateHooks(ctx, repo, false); err != nil { return fmt.Errorf("SyncRepositoryHook: %w", err) } if repo.HasWiki() { - if err := repo_module.CreateDelegateHooks(repo.WikiPath()); err != nil { + if err := gitrepo.CreateDelegateHooks(ctx, repo, true); err != nil { return fmt.Errorf("SyncRepositoryHook: %w", err) } } diff --git a/services/repository/migrate.go b/services/repository/migrate.go index 2e901791b4adf..db68683249057 100644 --- a/services/repository/migrate.go +++ b/services/repository/migrate.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/migration" @@ -262,11 +263,11 @@ func cleanUpMigrateGitConfig(ctx context.Context, repoPath string) error { // 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 := repo_module.CreateDelegateHooks(repoPath); err != nil { + if err := gitrepo.CreateDelegateHooks(ctx, repo, false); err != nil { return repo, fmt.Errorf("createDelegateHooks: %w", err) } if repo.HasWiki() { - if err := repo_module.CreateDelegateHooks(repo.WikiPath()); err != nil { + if err := gitrepo.CreateDelegateHooks(ctx, repo, true); err != nil { return repo, fmt.Errorf("createDelegateHooks.(wiki): %w", err) } } diff --git a/services/repository/transfer.go b/services/repository/transfer.go index f48653072a813..8b14b29a214dd 100644 --- a/services/repository/transfer.go +++ b/services/repository/transfer.go @@ -18,6 +18,7 @@ import ( project_model "code.gitea.io/gitea/models/project" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" + "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/sync" @@ -82,7 +83,7 @@ func transferOwnership(ctx context.Context, doer *user_model.User, newOwnerName } if repoRenamed { - if err := util.Rename(repo_model.RepoPath(newOwnerName, repo.Name), repo_model.RepoPath(oldOwnerName, repo.Name)); err != nil { + if err := gitrepo.RenameDir(ctx, newOwnerName+"/"+repo.Name, oldOwnerName+"/"+repo.Name); err != nil { log.Critical("Unable to move repository %s/%s directory from %s back to correct place %s: %v", oldOwnerName, repo.Name, repo_model.RepoPath(newOwnerName, repo.Name), repo_model.RepoPath(oldOwnerName, repo.Name), err) } @@ -323,19 +324,12 @@ func changeRepositoryName(ctx context.Context, repo *repo_model.Repository, newR } } - newRepoPath := repo_model.RepoPath(repo.Owner.Name, newRepoName) - if err = util.Rename(repo.RepoPath(), newRepoPath); err != nil { - return fmt.Errorf("rename repository directory: %w", err) - } - - wikiPath := repo.WikiPath() - isExist, err := util.IsExist(wikiPath) - if err != nil { - log.Error("Unable to check if %s exists. Error: %v", wikiPath, err) + if err := gitrepo.RenameRepository(ctx, repo, newRepoName); err != nil { return err } - if isExist { - if err = util.Rename(wikiPath, repo_model.WikiPath(repo.Owner.Name, newRepoName)); err != nil { + + if repo.HasWiki() { + if err = gitrepo.RenameWikiRepository(ctx, repo, newRepoName); err != nil { return fmt.Errorf("rename repository wiki: %w", err) } } diff --git a/services/user/user.go b/services/user/user.go index 2287e36c716ac..bb4c7dbee7b35 100644 --- a/services/user/user.go +++ b/services/user/user.go @@ -18,6 +18,7 @@ import ( system_model "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/eventsource" + "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/storage" @@ -100,7 +101,7 @@ func RenameUser(ctx context.Context, u *user_model.User, newUserName string) err } // Do not fail if directory does not exist - if err = util.Rename(user_model.UserPath(oldUserName), user_model.UserPath(newUserName)); err != nil && !os.IsNotExist(err) { + if err = gitrepo.RenameDir(ctx, oldUserName, newUserName); err != nil && !os.IsNotExist(err) { u.Name = oldUserName u.LowerName = strings.ToLower(oldUserName) return fmt.Errorf("rename user directory: %w", err) @@ -109,7 +110,7 @@ func RenameUser(ctx context.Context, u *user_model.User, newUserName string) err if err = committer.Commit(); err != nil { u.Name = oldUserName u.LowerName = strings.ToLower(oldUserName) - if err2 := util.Rename(user_model.UserPath(newUserName), user_model.UserPath(oldUserName)); err2 != nil && !os.IsNotExist(err2) { + if err2 := gitrepo.RenameDir(ctx, newUserName, oldUserName); err2 != nil && !os.IsNotExist(err2) { log.Critical("Unable to rollback directory change during failed username change from: %s to: %s. DB Error: %v. Filesystem Error: %v", oldUserName, newUserName, err, err2) return fmt.Errorf("failed to rollback directory change during failed username change from: %s to: %s. DB Error: %w. Filesystem Error: %v", oldUserName, newUserName, err, err2) } diff --git a/services/webhook/notifier.go b/services/webhook/notifier.go index 53b1cc8c9cf72..807f82c021c84 100644 --- a/services/webhook/notifier.go +++ b/services/webhook/notifier.go @@ -587,7 +587,7 @@ func (m *webhookNotifier) IssueChangeMilestone(ctx context.Context, doer *user_m func (m *webhookNotifier) PushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { apiPusher := convert.ToUser(ctx, pusher, nil) - apiCommits, apiHeadCommit, err := commits.ToAPIPayloadCommits(ctx, repo.RepoPath(), repo.HTMLURL()) + apiCommits, apiHeadCommit, err := commits.ToAPIPayloadCommits(ctx, repo, repo.HTMLURL()) if err != nil { log.Error("commits.ToAPIPayloadCommits failed: %v", err) return @@ -829,7 +829,7 @@ func (m *webhookNotifier) DeleteRelease(ctx context.Context, doer *user_model.Us func (m *webhookNotifier) SyncPushCommits(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) { apiPusher := convert.ToUser(ctx, pusher, nil) - apiCommits, apiHeadCommit, err := commits.ToAPIPayloadCommits(ctx, repo.RepoPath(), repo.HTMLURL()) + apiCommits, apiHeadCommit, err := commits.ToAPIPayloadCommits(ctx, repo, repo.HTMLURL()) if err != nil { log.Error("commits.ToAPIPayloadCommits failed: %v", err) return diff --git a/services/wiki/wiki.go b/services/wiki/wiki.go index fdcc5feefa7ec..8221e297d920f 100644 --- a/services/wiki/wiki.go +++ b/services/wiki/wiki.go @@ -40,7 +40,7 @@ func InitWiki(ctx context.Context, repo *repo_model.Repository) error { if err := git.InitRepository(ctx, repo.WikiPath(), true, repo.ObjectFormatName); err != nil { return fmt.Errorf("InitRepository: %w", err) - } else if err = repo_module.CreateDelegateHooks(repo.WikiPath()); err != nil { + } else if err = gitrepo.CreateDelegateHooks(ctx, repo, true); err != nil { return fmt.Errorf("createDelegateHooks: %w", err) } else if _, _, err = git.NewCommand(ctx, "symbolic-ref", "HEAD").AddDynamicArguments(git.BranchPrefix + repo.DefaultWikiBranch).RunStdString(&git.RunOpts{Dir: repo.WikiPath()}); err != nil { return fmt.Errorf("unable to set default wiki branch to %q: %w", repo.DefaultWikiBranch, err) @@ -96,7 +96,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model return fmt.Errorf("InitWiki: %w", err) } - hasDefaultBranch := git.IsBranchExist(ctx, repo.WikiPath(), repo.DefaultWikiBranch) + hasDefaultBranch := gitrepo.IsWikiBranchExist(ctx, repo, repo.DefaultWikiBranch) basePath, err := repo_module.CreateTemporaryPath("update-wiki") if err != nil {