From a7eceb57a9a67e15ce97d255e706abcd5aff36f4 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 17 Oct 2025 20:00:44 -0700 Subject: [PATCH] Use gitrepo.Repository instead of wikipath (#35398) Now the wikipath will not be referenced directly. --- models/repo/repo.go | 10 ----- models/repo/wiki.go | 13 +++---- models/repo/wiki_test.go | 13 ++----- modules/git/key.go | 53 ++++++++++++++++++++++++++- modules/gitrepo/clone.go | 20 ++++++++++ modules/gitrepo/commitgraph.go | 14 +++++++ modules/gitrepo/gitrepo.go | 12 ++++++ modules/gitrepo/push.go | 14 +++++++ modules/gitrepo/signing.go | 14 +++++++ routers/web/repo/githttp.go | 52 +++++++++----------------- routers/web/repo/setting/setting.go | 5 +-- services/asymkey/sign.go | 57 +++-------------------------- services/mirror/mirror_pull.go | 10 ++--- services/mirror/mirror_push.go | 10 ++--- services/repository/migrate.go | 23 ++++++------ services/repository/transfer.go | 18 +++++---- services/wiki/wiki.go | 4 +- 17 files changed, 191 insertions(+), 151 deletions(-) create mode 100644 modules/gitrepo/clone.go create mode 100644 modules/gitrepo/commitgraph.go create mode 100644 modules/gitrepo/push.go create mode 100644 modules/gitrepo/signing.go diff --git a/models/repo/repo.go b/models/repo/repo.go index 401775047b..819356dfad 100644 --- a/models/repo/repo.go +++ b/models/repo/repo.go @@ -229,10 +229,6 @@ func RelativePath(ownerName, repoName string) string { return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".git" } -func RelativeWikiPath(ownerName, repoName string) string { - return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".wiki.git" -} - // RelativePath should be an unix style path like username/reponame.git func (repo *Repository) RelativePath() string { return RelativePath(repo.OwnerName, repo.Name) @@ -245,12 +241,6 @@ func (sr StorageRepo) RelativePath() string { return string(sr) } -// WikiStorageRepo returns the storage repo for the wiki -// The wiki repository should have the same object format as the code repository -func (repo *Repository) WikiStorageRepo() StorageRepo { - return StorageRepo(RelativeWikiPath(repo.OwnerName, repo.Name)) -} - // SanitizedOriginalURL returns a sanitized OriginalURL func (repo *Repository) SanitizedOriginalURL() string { if repo.OriginalURL == "" { diff --git a/models/repo/wiki.go b/models/repo/wiki.go index 9f41445bf8..47c8fa43ab 100644 --- a/models/repo/wiki.go +++ b/models/repo/wiki.go @@ -7,7 +7,6 @@ package repo import ( "context" "fmt" - "path/filepath" "strings" user_model "code.gitea.io/gitea/models/user" @@ -76,12 +75,12 @@ func (repo *Repository) WikiCloneLink(ctx context.Context, doer *user_model.User return repo.cloneLink(ctx, doer, repo.Name+".wiki") } -// WikiPath returns wiki data path by given user and repository name. -func WikiPath(userName, repoName string) string { - return filepath.Join(user_model.UserPath(userName), strings.ToLower(repoName)+".wiki.git") +func RelativeWikiPath(ownerName, repoName string) string { + return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".wiki.git" } -// WikiPath returns wiki data path for given repository. -func (repo *Repository) WikiPath() string { - return WikiPath(repo.OwnerName, repo.Name) +// WikiStorageRepo returns the storage repo for the wiki +// The wiki repository should have the same object format as the code repository +func (repo *Repository) WikiStorageRepo() StorageRepo { + return StorageRepo(RelativeWikiPath(repo.OwnerName, repo.Name)) } diff --git a/models/repo/wiki_test.go b/models/repo/wiki_test.go index 41e53d93d9..636c78009b 100644 --- a/models/repo/wiki_test.go +++ b/models/repo/wiki_test.go @@ -4,12 +4,10 @@ package repo_test import ( - "path/filepath" "testing" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/modules/setting" "github.com/stretchr/testify/assert" ) @@ -23,15 +21,10 @@ func TestRepository_WikiCloneLink(t *testing.T) { assert.Equal(t, "https://try.gitea.io/user2/repo1.wiki.git", cloneLink.HTTPS) } -func TestWikiPath(t *testing.T) { +func TestRepository_RelativeWikiPath(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - expected := filepath.Join(setting.RepoRootPath, "user2/repo1.wiki.git") - assert.Equal(t, expected, repo_model.WikiPath("user2", "repo1")) -} -func TestRepository_WikiPath(t *testing.T) { - assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - expected := filepath.Join(setting.RepoRootPath, "user2/repo1.wiki.git") - assert.Equal(t, expected, repo.WikiPath()) + assert.Equal(t, "user2/repo1.wiki.git", repo_model.RelativeWikiPath(repo.OwnerName, repo.Name)) + assert.Equal(t, "user2/repo1.wiki.git", repo.WikiStorageRepo().RelativePath()) } diff --git a/modules/git/key.go b/modules/git/key.go index 8c14742f34..39e79ddbe0 100644 --- a/modules/git/key.go +++ b/modules/git/key.go @@ -3,7 +3,13 @@ package git -import "code.gitea.io/gitea/modules/setting" +import ( + "context" + "strings" + + "code.gitea.io/gitea/modules/git/gitcmd" + "code.gitea.io/gitea/modules/setting" +) // Based on https://git-scm.com/docs/git-config#Documentation/git-config.txt-gpgformat const ( @@ -24,3 +30,48 @@ func (s *SigningKey) String() string { setting.PanicInDevOrTesting("don't call SigningKey.String() - it exposes the KeyID which might be a local file path") return "SigningKey:" + s.Format } + +// GetSigningKey returns the KeyID and git Signature for the repo +func GetSigningKey(ctx context.Context, repoPath string) (*SigningKey, *Signature) { + if setting.Repository.Signing.SigningKey == "none" { + return nil, nil + } + + if setting.Repository.Signing.SigningKey == "default" || setting.Repository.Signing.SigningKey == "" { + // Can ignore the error here as it means that commit.gpgsign is not set + value, _, _ := gitcmd.NewCommand("config", "--get", "commit.gpgsign").WithDir(repoPath).RunStdString(ctx) + sign, valid := ParseBool(strings.TrimSpace(value)) + if !sign || !valid { + return nil, nil + } + + format, _, _ := gitcmd.NewCommand("config", "--default", SigningKeyFormatOpenPGP, "--get", "gpg.format").WithDir(repoPath).RunStdString(ctx) + signingKey, _, _ := gitcmd.NewCommand("config", "--get", "user.signingkey").WithDir(repoPath).RunStdString(ctx) + signingName, _, _ := gitcmd.NewCommand("config", "--get", "user.name").WithDir(repoPath).RunStdString(ctx) + signingEmail, _, _ := gitcmd.NewCommand("config", "--get", "user.email").WithDir(repoPath).RunStdString(ctx) + + if strings.TrimSpace(signingKey) == "" { + return nil, nil + } + + return &SigningKey{ + KeyID: strings.TrimSpace(signingKey), + Format: strings.TrimSpace(format), + }, &Signature{ + Name: strings.TrimSpace(signingName), + Email: strings.TrimSpace(signingEmail), + } + } + + if setting.Repository.Signing.SigningKey == "" { + return nil, nil + } + + return &SigningKey{ + KeyID: setting.Repository.Signing.SigningKey, + Format: setting.Repository.Signing.SigningFormat, + }, &Signature{ + Name: setting.Repository.Signing.SigningName, + Email: setting.Repository.Signing.SigningEmail, + } +} diff --git a/modules/gitrepo/clone.go b/modules/gitrepo/clone.go new file mode 100644 index 0000000000..8c437f657c --- /dev/null +++ b/modules/gitrepo/clone.go @@ -0,0 +1,20 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package gitrepo + +import ( + "context" + + "code.gitea.io/gitea/modules/git" +) + +// CloneExternalRepo clones an external repository to the managed repository. +func CloneExternalRepo(ctx context.Context, fromRemoteURL string, toRepo Repository, opts git.CloneRepoOptions) error { + return git.Clone(ctx, fromRemoteURL, repoPath(toRepo), opts) +} + +// CloneRepoToLocal clones a managed repository to a local path. +func CloneRepoToLocal(ctx context.Context, fromRepo Repository, toLocalPath string, opts git.CloneRepoOptions) error { + return git.Clone(ctx, repoPath(fromRepo), toLocalPath, opts) +} diff --git a/modules/gitrepo/commitgraph.go b/modules/gitrepo/commitgraph.go new file mode 100644 index 0000000000..7310e167f6 --- /dev/null +++ b/modules/gitrepo/commitgraph.go @@ -0,0 +1,14 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package gitrepo + +import ( + "context" + + "code.gitea.io/gitea/modules/git" +) + +func WriteCommitGraph(ctx context.Context, repo Repository) error { + return git.WriteCommitGraph(ctx, repoPath(repo)) +} diff --git a/modules/gitrepo/gitrepo.go b/modules/gitrepo/gitrepo.go index 59d2323599..4dd03c18fe 100644 --- a/modules/gitrepo/gitrepo.go +++ b/modules/gitrepo/gitrepo.go @@ -7,9 +7,12 @@ import ( "context" "fmt" "io" + "io/fs" + "os" "path/filepath" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/reqctx" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" @@ -86,3 +89,12 @@ func RenameRepository(ctx context.Context, repo, newRepo Repository) error { func InitRepository(ctx context.Context, repo Repository, objectFormatName string) error { return git.InitRepository(ctx, repoPath(repo), true, objectFormatName) } + +func UpdateServerInfo(ctx context.Context, repo Repository) error { + _, _, err := RunCmdBytes(ctx, repo, gitcmd.NewCommand("update-server-info")) + return err +} + +func GetRepoFS(repo Repository) fs.FS { + return os.DirFS(repoPath(repo)) +} diff --git a/modules/gitrepo/push.go b/modules/gitrepo/push.go new file mode 100644 index 0000000000..18808cac24 --- /dev/null +++ b/modules/gitrepo/push.go @@ -0,0 +1,14 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package gitrepo + +import ( + "context" + + "code.gitea.io/gitea/modules/git" +) + +func Push(ctx context.Context, repo Repository, opts git.PushOptions) error { + return git.Push(ctx, repoPath(repo), opts) +} diff --git a/modules/gitrepo/signing.go b/modules/gitrepo/signing.go new file mode 100644 index 0000000000..c50978d15a --- /dev/null +++ b/modules/gitrepo/signing.go @@ -0,0 +1,14 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package gitrepo + +import ( + "context" + + "code.gitea.io/gitea/modules/git" +) + +func GetSigningKey(ctx context.Context, repo Repository) (*git.SigningKey, *git.Signature) { + return git.GetSigningKey(ctx, repoPath(repo)) +} diff --git a/routers/web/repo/githttp.go b/routers/web/repo/githttp.go index 1b7e75f84e..69b93dd060 100644 --- a/routers/web/repo/githttp.go +++ b/routers/web/repo/githttp.go @@ -7,11 +7,10 @@ package repo import ( "bytes" "compress/gzip" - gocontext "context" "fmt" "net/http" "os" - "path/filepath" + "path" "regexp" "slices" "strconv" @@ -27,6 +26,7 @@ import ( "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git/gitcmd" + "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" @@ -342,11 +342,11 @@ type serviceHandler struct { environ []string } -func (h *serviceHandler) getRepoDir() string { +func (h *serviceHandler) getStorageRepo() gitrepo.Repository { if h.isWiki { - return h.repo.WikiPath() + return h.repo.WikiStorageRepo() } - return h.repo.RepoPath() + return h.repo } func setHeaderNoCache(ctx *context.Context) { @@ -378,19 +378,10 @@ func (h *serviceHandler) sendFile(ctx *context.Context, contentType, file string ctx.Resp.WriteHeader(http.StatusBadRequest) return } - reqFile := filepath.Join(h.getRepoDir(), filepath.Clean(file)) - - fi, err := os.Stat(reqFile) - if os.IsNotExist(err) { - ctx.Resp.WriteHeader(http.StatusNotFound) - return - } + fs := gitrepo.GetRepoFS(h.getStorageRepo()) ctx.Resp.Header().Set("Content-Type", contentType) - ctx.Resp.Header().Set("Content-Length", strconv.FormatInt(fi.Size(), 10)) - // http.TimeFormat required a UTC time, refer to https://pkg.go.dev/net/http#TimeFormat - ctx.Resp.Header().Set("Last-Modified", fi.ModTime().UTC().Format(http.TimeFormat)) - http.ServeFile(ctx.Resp, ctx.Req, reqFile) + http.ServeFileFS(ctx.Resp, ctx.Req, fs, path.Clean(file)) } // one or more key=value pairs separated by colons @@ -416,6 +407,7 @@ func serviceRPC(ctx *context.Context, h *serviceHandler, service string) { expectedContentType := fmt.Sprintf("application/x-git-%s-request", service) if ctx.Req.Header.Get("Content-Type") != expectedContentType { log.Error("Content-Type (%q) doesn't match expected: %q", ctx.Req.Header.Get("Content-Type"), expectedContentType) + // FIXME: why it's 401 if the content type is unexpected? ctx.Resp.WriteHeader(http.StatusUnauthorized) return } @@ -423,6 +415,7 @@ func serviceRPC(ctx *context.Context, h *serviceHandler, service string) { cmd, err := prepareGitCmdWithAllowedService(service) if err != nil { log.Error("Failed to prepareGitCmdWithService: %v", err) + // FIXME: why it's 401 if the service type doesn't supported? ctx.Resp.WriteHeader(http.StatusUnauthorized) return } @@ -449,17 +442,14 @@ func serviceRPC(ctx *context.Context, h *serviceHandler, service string) { } var stderr bytes.Buffer - if err := cmd.AddArguments("--stateless-rpc"). - AddDynamicArguments(h.getRepoDir()). - WithDir(h.getRepoDir()). + if err := gitrepo.RunCmd(ctx, h.getStorageRepo(), cmd.AddArguments("--stateless-rpc", "."). WithEnv(append(os.Environ(), h.environ...)). WithStderr(&stderr). WithStdin(reqBody). WithStdout(ctx.Resp). - WithUseContextTimeout(true). - Run(ctx); err != nil { + WithUseContextTimeout(true)); err != nil { if !git.IsErrCanceledOrKilled(err) { - log.Error("Fail to serve RPC(%s) in %s: %v - %s", service, h.getRepoDir(), err, stderr.String()) + log.Error("Fail to serve RPC(%s) in %s: %v - %s", service, h.getStorageRepo().RelativePath(), err, stderr.String()) } return } @@ -496,14 +486,6 @@ func getServiceType(ctx *context.Context) string { return "" } -func updateServerInfo(ctx gocontext.Context, dir string) []byte { - out, _, err := gitcmd.NewCommand("update-server-info").WithDir(dir).RunStdBytes(ctx) - if err != nil { - log.Error(fmt.Sprintf("%v - %s", err, string(out))) - } - return out -} - func packetWrite(str string) []byte { s := strconv.FormatInt(int64(len(str)+4), 16) if len(s)%4 != 0 { @@ -527,10 +509,8 @@ func GetInfoRefs(ctx *context.Context) { } h.environ = append(os.Environ(), h.environ...) - refs, _, err := cmd.AddArguments("--stateless-rpc", "--advertise-refs", "."). - WithEnv(h.environ). - WithDir(h.getRepoDir()). - RunStdBytes(ctx) + refs, _, err := gitrepo.RunCmdBytes(ctx, h.getStorageRepo(), cmd.AddArguments("--stateless-rpc", "--advertise-refs", "."). + WithEnv(h.environ)) if err != nil { log.Error(fmt.Sprintf("%v - %s", err, string(refs))) } @@ -541,7 +521,9 @@ func GetInfoRefs(ctx *context.Context) { _, _ = ctx.Resp.Write([]byte("0000")) _, _ = ctx.Resp.Write(refs) } else { - updateServerInfo(ctx, h.getRepoDir()) + if err := gitrepo.UpdateServerInfo(ctx, h.getStorageRepo()); err != nil { + log.Error("Failed to update server info: %v", err) + } h.sendFile(ctx, "text/plain; charset=utf-8", "info/refs") } } diff --git a/routers/web/repo/setting/setting.go b/routers/web/repo/setting/setting.go index 1a4f590e10..dd887d6edf 100644 --- a/routers/web/repo/setting/setting.go +++ b/routers/web/repo/setting/setting.go @@ -29,7 +29,6 @@ import ( "code.gitea.io/gitea/modules/validation" "code.gitea.io/gitea/modules/web" actions_service "code.gitea.io/gitea/services/actions" - asymkey_service "code.gitea.io/gitea/services/asymkey" "code.gitea.io/gitea/services/context" "code.gitea.io/gitea/services/forms" "code.gitea.io/gitea/services/migrations" @@ -62,7 +61,7 @@ func SettingsCtxData(ctx *context.Context) { ctx.Data["MinimumMirrorInterval"] = setting.Mirror.MinInterval ctx.Data["CanConvertFork"] = ctx.Repo.Repository.IsFork && ctx.Doer.CanCreateRepoIn(ctx.Repo.Repository.Owner) - signing, _ := asymkey_service.SigningKey(ctx, ctx.Repo.Repository.RepoPath()) + signing, _ := gitrepo.GetSigningKey(ctx, ctx.Repo.Repository) ctx.Data["SigningKeyAvailable"] = signing != nil ctx.Data["SigningSettings"] = setting.Repository.Signing ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled @@ -105,7 +104,7 @@ func SettingsPost(ctx *context.Context) { ctx.Data["DefaultMirrorInterval"] = setting.Mirror.DefaultInterval ctx.Data["MinimumMirrorInterval"] = setting.Mirror.MinInterval - signing, _ := asymkey_service.SigningKey(ctx, ctx.Repo.Repository.RepoPath()) + signing, _ := gitrepo.GetSigningKey(ctx, ctx.Repo.Repository) ctx.Data["SigningKeyAvailable"] = signing != nil ctx.Data["SigningSettings"] = setting.Repository.Signing ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled diff --git a/services/asymkey/sign.go b/services/asymkey/sign.go index 61b9e56d95..1ed05ba287 100644 --- a/services/asymkey/sign.go +++ b/services/asymkey/sign.go @@ -17,7 +17,6 @@ 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/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" @@ -109,54 +108,9 @@ func IsErrWontSign(err error) bool { return ok } -// SigningKey returns the KeyID and git Signature for the repo -func SigningKey(ctx context.Context, repoPath string) (*git.SigningKey, *git.Signature) { - if setting.Repository.Signing.SigningKey == "none" { - return nil, nil - } - - if setting.Repository.Signing.SigningKey == "default" || setting.Repository.Signing.SigningKey == "" { - // Can ignore the error here as it means that commit.gpgsign is not set - value, _, _ := gitcmd.NewCommand("config", "--get", "commit.gpgsign").WithDir(repoPath).RunStdString(ctx) - sign, valid := git.ParseBool(strings.TrimSpace(value)) - if !sign || !valid { - return nil, nil - } - - format, _, _ := gitcmd.NewCommand("config", "--default", git.SigningKeyFormatOpenPGP, "--get", "gpg.format").WithDir(repoPath).RunStdString(ctx) - signingKey, _, _ := gitcmd.NewCommand("config", "--get", "user.signingkey").WithDir(repoPath).RunStdString(ctx) - signingName, _, _ := gitcmd.NewCommand("config", "--get", "user.name").WithDir(repoPath).RunStdString(ctx) - signingEmail, _, _ := gitcmd.NewCommand("config", "--get", "user.email").WithDir(repoPath).RunStdString(ctx) - - if strings.TrimSpace(signingKey) == "" { - return nil, nil - } - - return &git.SigningKey{ - KeyID: strings.TrimSpace(signingKey), - Format: strings.TrimSpace(format), - }, &git.Signature{ - Name: strings.TrimSpace(signingName), - Email: strings.TrimSpace(signingEmail), - } - } - - if setting.Repository.Signing.SigningKey == "" { - return nil, nil - } - - return &git.SigningKey{ - KeyID: setting.Repository.Signing.SigningKey, - Format: setting.Repository.Signing.SigningFormat, - }, &git.Signature{ - Name: setting.Repository.Signing.SigningName, - Email: setting.Repository.Signing.SigningEmail, - } -} - // PublicSigningKey gets the public signing key within a provided repository directory func PublicSigningKey(ctx context.Context, repoPath string) (content, format string, err error) { - signingKey, _ := SigningKey(ctx, repoPath) + signingKey, _ := git.GetSigningKey(ctx, repoPath) if signingKey == nil { return "", "", nil } @@ -181,7 +135,7 @@ func PublicSigningKey(ctx context.Context, repoPath string) (content, format str // SignInitialCommit determines if we should sign the initial commit to this repository func SignInitialCommit(ctx context.Context, repoPath string, u *user_model.User) (bool, *git.SigningKey, *git.Signature, error) { rules := signingModeFromStrings(setting.Repository.Signing.InitialCommit) - signingKey, sig := SigningKey(ctx, repoPath) + signingKey, sig := git.GetSigningKey(ctx, repoPath) if signingKey == nil { return false, nil, nil, &ErrWontSign{noKey} } @@ -216,9 +170,8 @@ Loop: // SignWikiCommit determines if we should sign the commits to this repository wiki func SignWikiCommit(ctx context.Context, repo *repo_model.Repository, u *user_model.User) (bool, *git.SigningKey, *git.Signature, error) { - repoWikiPath := repo.WikiPath() rules := signingModeFromStrings(setting.Repository.Signing.Wiki) - signingKey, sig := SigningKey(ctx, repoWikiPath) + signingKey, sig := gitrepo.GetSigningKey(ctx, repo.WikiStorageRepo()) if signingKey == nil { return false, nil, nil, &ErrWontSign{noKey} } @@ -271,7 +224,7 @@ Loop: // SignCRUDAction determines if we should sign a CRUD commit to this repository func SignCRUDAction(ctx context.Context, repoPath string, u *user_model.User, tmpBasePath, parentCommit string) (bool, *git.SigningKey, *git.Signature, error) { rules := signingModeFromStrings(setting.Repository.Signing.CRUDActions) - signingKey, sig := SigningKey(ctx, repoPath) + signingKey, sig := git.GetSigningKey(ctx, repoPath) if signingKey == nil { return false, nil, nil, &ErrWontSign{noKey} } @@ -335,7 +288,7 @@ func SignMerge(ctx context.Context, pr *issues_model.PullRequest, u *user_model. } repo := pr.BaseRepo - signingKey, signer := SigningKey(ctx, repo.RepoPath()) + signingKey, signer := gitrepo.GetSigningKey(ctx, repo) if signingKey == nil { return false, nil, nil, &ErrWontSign{noKey} } diff --git a/services/mirror/mirror_pull.go b/services/mirror/mirror_pull.go index 4b19112d3c..da58bbd1b6 100644 --- a/services/mirror/mirror_pull.go +++ b/services/mirror/mirror_pull.go @@ -249,8 +249,6 @@ func checkRecoverableSyncError(stderrMessage string) bool { // runSync returns true if sync finished without error. func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bool) { - repoPath := m.Repo.RepoPath() - wikiPath := m.Repo.WikiPath() timeout := time.Duration(setting.Git.Timeout.Mirror) * time.Second log.Trace("SyncMirrors [repo: %-v]: running git remote update...", m.Repo) @@ -311,7 +309,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo // If there is still an error (or there always was an error) if err != nil { log.Error("SyncMirrors [repo: %-v]: failed to update mirror repository:\nStdout: %s\nStderr: %s\nErr: %v", m.Repo, stdoutMessage, stderrMessage, err) - desc := fmt.Sprintf("Failed to update mirror repository '%s': %s", repoPath, stderrMessage) + desc := fmt.Sprintf("Failed to update mirror repository '%s': %s", m.Repo.RelativePath(), stderrMessage) if err = system_model.CreateRepositoryNotice(desc); err != nil { log.Error("CreateRepositoryNotice: %v", err) } @@ -320,7 +318,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo } output := stderrBuilder.String() - if err := git.WriteCommitGraph(ctx, repoPath); err != nil { + if err := gitrepo.WriteCommitGraph(ctx, m.Repo); err != nil { log.Error("SyncMirrors [repo: %-v]: %v", m.Repo, err) } @@ -394,14 +392,14 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo // If there is still an error (or there always was an error) if err != nil { log.Error("SyncMirrors [repo: %-v Wiki]: failed to update mirror repository wiki:\nStdout: %s\nStderr: %s\nErr: %v", m.Repo, stdoutMessage, stderrMessage, err) - desc := fmt.Sprintf("Failed to update mirror repository wiki '%s': %s", wikiPath, stderrMessage) + desc := fmt.Sprintf("Failed to update mirror repository wiki '%s': %s", m.Repo.WikiStorageRepo().RelativePath(), stderrMessage) if err = system_model.CreateRepositoryNotice(desc); err != nil { log.Error("CreateRepositoryNotice: %v", err) } return nil, false } - if err := git.WriteCommitGraph(ctx, wikiPath); err != nil { + if err := gitrepo.WriteCommitGraph(ctx, m.Repo.WikiStorageRepo()); err != nil { log.Error("SyncMirrors [repo: %-v]: %v", m.Repo, err) } } diff --git a/services/mirror/mirror_push.go b/services/mirror/mirror_push.go index 9a832a1350..b61345e830 100644 --- a/services/mirror/mirror_push.go +++ b/services/mirror/mirror_push.go @@ -124,14 +124,12 @@ func runPushSync(ctx context.Context, m *repo_model.PushMirror) error { performPush := func(repo *repo_model.Repository, isWiki bool) error { var storageRepo gitrepo.Repository = repo - path := repo.RepoPath() if isWiki { storageRepo = repo.WikiStorageRepo() - path = repo.WikiPath() } remoteURL, err := gitrepo.GitRemoteGetURL(ctx, storageRepo, m.RemoteName) if err != nil { - log.Error("GetRemoteURL(%s) Error %v", path, err) + log.Error("GetRemoteURL(%s) Error %v", storageRepo.RelativePath(), err) return errors.New("Unexpected error") } @@ -152,17 +150,17 @@ func runPushSync(ctx context.Context, m *repo_model.PushMirror) error { } } - log.Trace("Pushing %s mirror[%d] remote %s", path, m.ID, m.RemoteName) + log.Trace("Pushing %s mirror[%d] remote %s", storageRepo.RelativePath(), m.ID, m.RemoteName) envs := proxy.EnvWithProxy(remoteURL.URL) - if err := git.Push(ctx, path, git.PushOptions{ + if err := gitrepo.Push(ctx, storageRepo, git.PushOptions{ Remote: m.RemoteName, Force: true, Mirror: true, Timeout: timeout, Env: envs, }); err != nil { - log.Error("Error pushing %s mirror[%d] remote %s: %v", path, m.ID, m.RemoteName, err) + log.Error("Error pushing %s mirror[%d] remote %s: %v", storageRepo.RelativePath(), m.ID, m.RemoteName, err) return util.SanitizeErrorCredentialURLs(err) } diff --git a/services/repository/migrate.go b/services/repository/migrate.go index 9873d5deeb..acac6fd9ad 100644 --- a/services/repository/migrate.go +++ b/services/repository/migrate.go @@ -28,22 +28,23 @@ import ( ) func cloneWiki(ctx context.Context, repo *repo_model.Repository, opts migration.MigrateOptions, migrateTimeout time.Duration) (string, error) { - wikiPath := repo.WikiPath() - wikiRemotePath := repo_module.WikiRemoteURL(ctx, opts.CloneAddr) - if wikiRemotePath == "" { + wikiRemoteURL := repo_module.WikiRemoteURL(ctx, opts.CloneAddr) + if wikiRemoteURL == "" { return "", nil } - if err := util.RemoveAll(wikiPath); err != nil { - return "", fmt.Errorf("failed to remove existing wiki dir %q, err: %w", wikiPath, err) + storageRepo := repo.WikiStorageRepo() + + if err := gitrepo.DeleteRepository(ctx, storageRepo); err != nil { + return "", fmt.Errorf("failed to remove existing wiki dir %q, err: %w", storageRepo.RelativePath(), err) } cleanIncompleteWikiPath := func() { - if err := util.RemoveAll(wikiPath); err != nil { - log.Error("Failed to remove incomplete wiki dir %q, err: %v", wikiPath, err) + if err := gitrepo.DeleteRepository(ctx, storageRepo); err != nil { + log.Error("Failed to remove incomplete wiki dir %q, err: %v", storageRepo.RelativePath(), err) } } - if err := git.Clone(ctx, wikiRemotePath, wikiPath, git.CloneRepoOptions{ + if err := gitrepo.CloneExternalRepo(ctx, wikiRemoteURL, storageRepo, git.CloneRepoOptions{ Mirror: true, Quiet: true, Timeout: migrateTimeout, @@ -54,15 +55,15 @@ func cloneWiki(ctx context.Context, repo *repo_model.Repository, opts migration. return "", err } - if err := git.WriteCommitGraph(ctx, wikiPath); err != nil { + if err := gitrepo.WriteCommitGraph(ctx, storageRepo); err != nil { cleanIncompleteWikiPath() return "", err } - defaultBranch, err := gitrepo.GetDefaultBranch(ctx, repo.WikiStorageRepo()) + defaultBranch, err := gitrepo.GetDefaultBranch(ctx, storageRepo) if err != nil { cleanIncompleteWikiPath() - return "", fmt.Errorf("failed to get wiki repo default branch for %q, err: %w", wikiPath, err) + return "", fmt.Errorf("failed to get wiki repo default branch for %q, err: %w", storageRepo.RelativePath(), err) } return defaultBranch, nil diff --git a/services/repository/transfer.go b/services/repository/transfer.go index c30a540137..98307a447a 100644 --- a/services/repository/transfer.go +++ b/services/repository/transfer.go @@ -107,16 +107,18 @@ 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 { + oldRelativePath, newRelativePath := repo_model.RelativePath(newOwnerName, repo.Name), repo_model.RelativePath(oldOwnerName, repo.Name) + if err := gitrepo.RenameRepository(ctx, repo_model.StorageRepo(oldRelativePath), repo_model.StorageRepo(newRelativePath)); 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) + oldRelativePath, newRelativePath, err) } } if wikiRenamed { - if err := util.Rename(repo_model.WikiPath(newOwnerName, repo.Name), repo_model.WikiPath(oldOwnerName, repo.Name)); err != nil { + oldRelativePath, newRelativePath := repo_model.RelativeWikiPath(newOwnerName, repo.Name), repo_model.RelativeWikiPath(oldOwnerName, repo.Name) + if err := gitrepo.RenameRepository(ctx, repo_model.StorageRepo(oldRelativePath), repo_model.StorageRepo(newRelativePath)); err != nil { log.Critical("Unable to move wiki for repository %s/%s directory from %s back to correct place %s: %v", oldOwnerName, repo.Name, - repo_model.WikiPath(newOwnerName, repo.Name), repo_model.WikiPath(oldOwnerName, repo.Name), err) + oldRelativePath, newRelativePath, err) } } @@ -289,12 +291,12 @@ func transferOwnership(ctx context.Context, doer *user_model.User, newOwnerName repoRenamed = true // Rename remote wiki repository to new path and delete local copy. - wikiPath := repo_model.WikiPath(oldOwner.Name, repo.Name) - if isExist, err := util.IsExist(wikiPath); err != nil { - log.Error("Unable to check if %s exists. Error: %v", wikiPath, err) + wikiStorageRepo := repo_model.StorageRepo(repo_model.RelativeWikiPath(oldOwner.Name, repo.Name)) + if isExist, err := gitrepo.IsRepositoryExist(ctx, wikiStorageRepo); err != nil { + log.Error("Unable to check if %s exists. Error: %v", wikiStorageRepo.RelativePath(), err) return err } else if isExist { - if err := util.Rename(wikiPath, repo_model.WikiPath(newOwner.Name, repo.Name)); err != nil { + if err := gitrepo.RenameRepository(ctx, wikiStorageRepo, repo_model.StorageRepo(repo_model.RelativeWikiPath(newOwner.Name, repo.Name))); err != nil { return fmt.Errorf("rename repository wiki: %w", err) } wikiRenamed = true diff --git a/services/wiki/wiki.go b/services/wiki/wiki.go index 25c33b57fc..25f836dd5d 100644 --- a/services/wiki/wiki.go +++ b/services/wiki/wiki.go @@ -120,7 +120,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model cloneOpts.Branch = repo.DefaultWikiBranch } - if err := git.Clone(ctx, repo.WikiPath(), basePath, cloneOpts); err != nil { + if err := gitrepo.CloneRepoToLocal(ctx, repo.WikiStorageRepo(), basePath, cloneOpts); err != nil { log.Error("Failed to clone repository: %s (%v)", repo.FullName(), err) return fmt.Errorf("failed to clone repository: %s (%w)", repo.FullName(), err) } @@ -269,7 +269,7 @@ func DeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model } defer cleanup() - if err := git.Clone(ctx, repo.WikiPath(), basePath, git.CloneRepoOptions{ + if err := gitrepo.CloneRepoToLocal(ctx, repo.WikiStorageRepo(), basePath, git.CloneRepoOptions{ Bare: true, Shared: true, Branch: repo.DefaultWikiBranch,