Skip to content

Commit e5b8200

Browse files
committed
Use gitrepo.Repository instead of most of wikipath
1 parent 1717af7 commit e5b8200

File tree

14 files changed

+167
-98
lines changed

14 files changed

+167
-98
lines changed

models/repo/repo.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -229,10 +229,6 @@ func RelativePath(ownerName, repoName string) string {
229229
return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".git"
230230
}
231231

232-
func RelativeWikiPath(ownerName, repoName string) string {
233-
return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".wiki.git"
234-
}
235-
236232
// RelativePath should be an unix style path like username/reponame.git
237233
func (repo *Repository) RelativePath() string {
238234
return RelativePath(repo.OwnerName, repo.Name)
@@ -245,12 +241,6 @@ func (sr StorageRepo) RelativePath() string {
245241
return string(sr)
246242
}
247243

248-
// WikiStorageRepo returns the storage repo for the wiki
249-
// The wiki repository should have the same object format as the code repository
250-
func (repo *Repository) WikiStorageRepo() StorageRepo {
251-
return StorageRepo(RelativeWikiPath(repo.OwnerName, repo.Name))
252-
}
253-
254244
// SanitizedOriginalURL returns a sanitized OriginalURL
255245
func (repo *Repository) SanitizedOriginalURL() string {
256246
if repo.OriginalURL == "" {

models/repo/wiki.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,17 @@ func (repo *Repository) WikiCloneLink(ctx context.Context, doer *user_model.User
7676
return repo.cloneLink(ctx, doer, repo.Name+".wiki")
7777
}
7878

79-
// WikiPath returns wiki data path by given user and repository name.
80-
func WikiPath(userName, repoName string) string {
81-
return filepath.Join(user_model.UserPath(userName), strings.ToLower(repoName)+".wiki.git")
79+
func RelativeWikiPath(ownerName, repoName string) string {
80+
return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".wiki.git"
81+
}
82+
83+
// WikiStorageRepo returns the storage repo for the wiki
84+
// The wiki repository should have the same object format as the code repository
85+
func (repo *Repository) WikiStorageRepo() StorageRepo {
86+
return StorageRepo(RelativeWikiPath(repo.OwnerName, repo.Name))
8287
}
8388

8489
// WikiPath returns wiki data path for given repository.
8590
func (repo *Repository) WikiPath() string {
86-
return WikiPath(repo.OwnerName, repo.Name)
91+
return filepath.Join(user_model.UserPath(repo.OwnerName), strings.ToLower(repo.Name)+".wiki.git")
8792
}

models/repo/wiki_test.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,6 @@ func TestRepository_WikiCloneLink(t *testing.T) {
2323
assert.Equal(t, "https://try.gitea.io/user2/repo1.wiki.git", cloneLink.HTTPS)
2424
}
2525

26-
func TestWikiPath(t *testing.T) {
27-
assert.NoError(t, unittest.PrepareTestDatabase())
28-
expected := filepath.Join(setting.RepoRootPath, "user2/repo1.wiki.git")
29-
assert.Equal(t, expected, repo_model.WikiPath("user2", "repo1"))
30-
}
31-
3226
func TestRepository_WikiPath(t *testing.T) {
3327
assert.NoError(t, unittest.PrepareTestDatabase())
3428
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})

modules/gitrepo/clone.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package gitrepo
5+
6+
import (
7+
"context"
8+
9+
"code.gitea.io/gitea/modules/git"
10+
)
11+
12+
func CloneIn(ctx context.Context, dstRepo Repository, from string, opts git.CloneRepoOptions) error {
13+
return git.Clone(ctx, from, repoPath(dstRepo), opts)
14+
}
15+
16+
func CloneOut(ctx context.Context, fromRepo Repository, to string, opts git.CloneRepoOptions) error {
17+
return git.Clone(ctx, repoPath(fromRepo), to, opts)
18+
}

modules/gitrepo/commitgraph.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package gitrepo
5+
6+
import (
7+
"context"
8+
9+
"code.gitea.io/gitea/modules/git"
10+
)
11+
12+
func WriteCommitGraph(ctx context.Context, repo Repository) error {
13+
return git.WriteCommitGraph(ctx, repoPath(repo))
14+
}

modules/gitrepo/gitrepo.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"context"
88
"fmt"
99
"io"
10+
"io/fs"
11+
"os"
1012
"path/filepath"
1113

1214
"code.gitea.io/gitea/modules/git"
@@ -86,3 +88,12 @@ func RenameRepository(ctx context.Context, repo, newRepo Repository) error {
8688
func InitRepository(ctx context.Context, repo Repository, objectFormatName string) error {
8789
return git.InitRepository(ctx, repoPath(repo), true, objectFormatName)
8890
}
91+
92+
func UpdateServerInfo(ctx context.Context, repo Repository) error {
93+
_, _, err := git.NewCommand("update-server-info").RunStdBytes(ctx, &git.RunOpts{Dir: repoPath(repo)})
94+
return err
95+
}
96+
97+
func GetRepoFS(repo Repository) fs.FS {
98+
return os.DirFS(repoPath(repo))
99+
}

modules/gitrepo/http.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package gitrepo
5+
6+
import (
7+
"bytes"
8+
"context"
9+
"io"
10+
"os"
11+
12+
"code.gitea.io/gitea/modules/git"
13+
)
14+
15+
func serviceCmd(service string) *git.Command {
16+
if service == "git-receive-pack" {
17+
return git.NewCommand("git-receive-pack")
18+
}
19+
return git.NewCommand("git-upload-pack")
20+
}
21+
22+
func StatelessRPC(ctx context.Context, storageRepo Repository, service string, extraEnvs []string, input io.Reader, output io.Writer) (string, error) {
23+
var stderr bytes.Buffer
24+
if err := serviceCmd(service).
25+
AddArguments("--stateless-rpc").
26+
AddDynamicArguments(repoPath(storageRepo)).
27+
Run(ctx, &git.RunOpts{
28+
Dir: repoPath(storageRepo),
29+
Env: append(os.Environ(), extraEnvs...),
30+
Stdout: output,
31+
Stdin: input,
32+
Stderr: &stderr,
33+
UseContextTimeout: true,
34+
}); err != nil {
35+
return stderr.String(), err
36+
}
37+
return "", nil
38+
}
39+
40+
func StatelessRPCAdvertiseRefs(ctx context.Context, storageRepo Repository, service string, extraEnvs []string) ([]byte, error) {
41+
refs, _, err := serviceCmd(service).AddArguments("--stateless-rpc", "--advertise-refs", ".").
42+
RunStdBytes(ctx, &git.RunOpts{
43+
Dir: repoPath(storageRepo),
44+
Env: append(os.Environ(), extraEnvs...),
45+
})
46+
return refs, err
47+
}

modules/gitrepo/push.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package gitrepo
5+
6+
import (
7+
"context"
8+
9+
"code.gitea.io/gitea/modules/git"
10+
)
11+
12+
func Push(ctx context.Context, repo Repository, opts git.PushOptions) error {
13+
return git.Push(ctx, repoPath(repo), opts)
14+
}

routers/web/repo/githttp.go

Lines changed: 24 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,10 @@
55
package repo
66

77
import (
8-
"bytes"
98
"compress/gzip"
10-
gocontext "context"
119
"fmt"
1210
"net/http"
1311
"os"
14-
"path/filepath"
1512
"regexp"
1613
"slices"
1714
"strconv"
@@ -26,6 +23,7 @@ import (
2623
repo_model "code.gitea.io/gitea/models/repo"
2724
"code.gitea.io/gitea/models/unit"
2825
"code.gitea.io/gitea/modules/git"
26+
"code.gitea.io/gitea/modules/gitrepo"
2927
"code.gitea.io/gitea/modules/log"
3028
repo_module "code.gitea.io/gitea/modules/repository"
3129
"code.gitea.io/gitea/modules/setting"
@@ -339,11 +337,11 @@ type serviceHandler struct {
339337
environ []string
340338
}
341339

342-
func (h *serviceHandler) getRepoDir() string {
340+
func (h *serviceHandler) getStorageRepo() gitrepo.Repository {
343341
if h.isWiki {
344-
return h.repo.WikiPath()
342+
return h.repo.WikiStorageRepo()
345343
}
346-
return h.repo.RepoPath()
344+
return h.repo
347345
}
348346

349347
func setHeaderNoCache(ctx *context.Context) {
@@ -375,9 +373,16 @@ func (h *serviceHandler) sendFile(ctx *context.Context, contentType, file string
375373
ctx.Resp.WriteHeader(http.StatusBadRequest)
376374
return
377375
}
378-
reqFile := filepath.Join(h.getRepoDir(), file)
379376

380-
fi, err := os.Stat(reqFile)
377+
fs := gitrepo.GetRepoFS(h.getStorageRepo())
378+
f, err := fs.Open(file)
379+
if err != nil {
380+
log.Error("Failed to open file: %v", err)
381+
return
382+
}
383+
defer f.Close()
384+
385+
fi, err := f.Stat()
381386
if os.IsNotExist(err) {
382387
ctx.Resp.WriteHeader(http.StatusNotFound)
383388
return
@@ -387,23 +392,12 @@ func (h *serviceHandler) sendFile(ctx *context.Context, contentType, file string
387392
ctx.Resp.Header().Set("Content-Length", strconv.FormatInt(fi.Size(), 10))
388393
// http.TimeFormat required a UTC time, refer to https://pkg.go.dev/net/http#TimeFormat
389394
ctx.Resp.Header().Set("Last-Modified", fi.ModTime().UTC().Format(http.TimeFormat))
390-
http.ServeFile(ctx.Resp, ctx.Req, reqFile)
395+
http.ServeFileFS(ctx.Resp, ctx.Req, fs, file)
391396
}
392397

393398
// one or more key=value pairs separated by colons
394399
var safeGitProtocolHeader = regexp.MustCompile(`^[0-9a-zA-Z]+=[0-9a-zA-Z]+(:[0-9a-zA-Z]+=[0-9a-zA-Z]+)*$`)
395400

396-
func prepareGitCmdWithAllowedService(service string) (*git.Command, error) {
397-
if service == "receive-pack" {
398-
return git.NewCommand("receive-pack"), nil
399-
}
400-
if service == "upload-pack" {
401-
return git.NewCommand("upload-pack"), nil
402-
}
403-
404-
return nil, fmt.Errorf("service %q is not allowed", service)
405-
}
406-
407401
func serviceRPC(ctx *context.Context, h *serviceHandler, service string) {
408402
defer func() {
409403
if err := ctx.Req.Body.Close(); err != nil {
@@ -418,17 +412,16 @@ func serviceRPC(ctx *context.Context, h *serviceHandler, service string) {
418412
return
419413
}
420414

421-
cmd, err := prepareGitCmdWithAllowedService(service)
422-
if err != nil {
423-
log.Error("Failed to prepareGitCmdWithService: %v", err)
415+
if service != "upload-pack" && service != "receive-pack" {
416+
log.Error("Invalid service: %q", service)
424417
ctx.Resp.WriteHeader(http.StatusUnauthorized)
425418
return
426419
}
427420

428421
ctx.Resp.Header().Set("Content-Type", fmt.Sprintf("application/x-git-%s-result", service))
429422

430423
reqBody := ctx.Req.Body
431-
424+
var err error
432425
// Handle GZIP.
433426
if ctx.Req.Header.Get("Content-Encoding") == "gzip" {
434427
reqBody, err = gzip.NewReader(reqBody)
@@ -446,18 +439,9 @@ func serviceRPC(ctx *context.Context, h *serviceHandler, service string) {
446439
h.environ = append(h.environ, "GIT_PROTOCOL="+protocol)
447440
}
448441

449-
var stderr bytes.Buffer
450-
cmd.AddArguments("--stateless-rpc").AddDynamicArguments(h.getRepoDir())
451-
if err := cmd.Run(ctx, &git.RunOpts{
452-
Dir: h.getRepoDir(),
453-
Env: append(os.Environ(), h.environ...),
454-
Stdout: ctx.Resp,
455-
Stdin: reqBody,
456-
Stderr: &stderr,
457-
UseContextTimeout: true,
458-
}); err != nil {
442+
if stderr, err := gitrepo.StatelessRPC(ctx, h.getStorageRepo(), service, h.environ, reqBody, ctx.Resp); err != nil {
459443
if !git.IsErrCanceledOrKilled(err) {
460-
log.Error("Fail to serve RPC(%s) in %s: %v - %s", service, h.getRepoDir(), err, stderr.String())
444+
log.Error("Fail to serve RPC(%s) in %s: %v - %s", service, h.getStorageRepo().RelativePath(), err, stderr)
461445
}
462446
return
463447
}
@@ -487,14 +471,6 @@ func getServiceType(ctx *context.Context) string {
487471
return strings.TrimPrefix(serviceType, "git-")
488472
}
489473

490-
func updateServerInfo(ctx gocontext.Context, dir string) []byte {
491-
out, _, err := git.NewCommand("update-server-info").RunStdBytes(ctx, &git.RunOpts{Dir: dir})
492-
if err != nil {
493-
log.Error(fmt.Sprintf("%v - %s", err, string(out)))
494-
}
495-
return out
496-
}
497-
498474
func packetWrite(str string) []byte {
499475
s := strconv.FormatInt(int64(len(str)+4), 16)
500476
if len(s)%4 != 0 {
@@ -511,14 +487,12 @@ func GetInfoRefs(ctx *context.Context) {
511487
}
512488
setHeaderNoCache(ctx)
513489
service := getServiceType(ctx)
514-
cmd, err := prepareGitCmdWithAllowedService(service)
515-
if err == nil {
490+
if service == "upload-pack" || service == "receive-pack" {
516491
if protocol := ctx.Req.Header.Get("Git-Protocol"); protocol != "" && safeGitProtocolHeader.MatchString(protocol) {
517492
h.environ = append(h.environ, "GIT_PROTOCOL="+protocol)
518493
}
519-
h.environ = append(os.Environ(), h.environ...)
520494

521-
refs, _, err := cmd.AddArguments("--stateless-rpc", "--advertise-refs", ".").RunStdBytes(ctx, &git.RunOpts{Env: h.environ, Dir: h.getRepoDir()})
495+
refs, err := gitrepo.StatelessRPCAdvertiseRefs(ctx, h.getStorageRepo(), service, h.environ)
522496
if err != nil {
523497
log.Error(fmt.Sprintf("%v - %s", err, string(refs)))
524498
}
@@ -529,7 +503,9 @@ func GetInfoRefs(ctx *context.Context) {
529503
_, _ = ctx.Resp.Write([]byte("0000"))
530504
_, _ = ctx.Resp.Write(refs)
531505
} else {
532-
updateServerInfo(ctx, h.getRepoDir())
506+
if err := gitrepo.UpdateServerInfo(ctx, h.getStorageRepo()); err != nil {
507+
log.Error("Failed to update server info: %v", err)
508+
}
533509
h.sendFile(ctx, "text/plain; charset=utf-8", "info/refs")
534510
}
535511
}

services/mirror/mirror_pull.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,6 @@ func checkRecoverableSyncError(stderrMessage string) bool {
249249
// runSync returns true if sync finished without error.
250250
func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bool) {
251251
repoPath := m.Repo.RepoPath()
252-
wikiPath := m.Repo.WikiPath()
253252
timeout := time.Duration(setting.Git.Timeout.Mirror) * time.Second
254253

255254
log.Trace("SyncMirrors [repo: %-v]: running git remote update...", m.Repo)
@@ -316,7 +315,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo
316315
// If there is still an error (or there always was an error)
317316
if err != nil {
318317
log.Error("SyncMirrors [repo: %-v]: failed to update mirror repository:\nStdout: %s\nStderr: %s\nErr: %v", m.Repo, stdoutMessage, stderrMessage, err)
319-
desc := fmt.Sprintf("Failed to update mirror repository '%s': %s", repoPath, stderrMessage)
318+
desc := fmt.Sprintf("Failed to update mirror repository '%s': %s", m.Repo.RelativePath(), stderrMessage)
320319
if err = system_model.CreateRepositoryNotice(desc); err != nil {
321320
log.Error("CreateRepositoryNotice: %v", err)
322321
}
@@ -325,7 +324,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo
325324
}
326325
output := stderrBuilder.String()
327326

328-
if err := git.WriteCommitGraph(ctx, repoPath); err != nil {
327+
if err := gitrepo.WriteCommitGraph(ctx, m.Repo); err != nil {
329328
log.Error("SyncMirrors [repo: %-v]: %v", m.Repo, err)
330329
}
331330

@@ -399,14 +398,14 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo
399398
// If there is still an error (or there always was an error)
400399
if err != nil {
401400
log.Error("SyncMirrors [repo: %-v Wiki]: failed to update mirror repository wiki:\nStdout: %s\nStderr: %s\nErr: %v", m.Repo, stdoutMessage, stderrMessage, err)
402-
desc := fmt.Sprintf("Failed to update mirror repository wiki '%s': %s", wikiPath, stderrMessage)
401+
desc := fmt.Sprintf("Failed to update mirror repository wiki '%s': %s", m.Repo.WikiStorageRepo().RelativePath(), stderrMessage)
403402
if err = system_model.CreateRepositoryNotice(desc); err != nil {
404403
log.Error("CreateRepositoryNotice: %v", err)
405404
}
406405
return nil, false
407406
}
408407

409-
if err := git.WriteCommitGraph(ctx, wikiPath); err != nil {
408+
if err := gitrepo.WriteCommitGraph(ctx, m.Repo.WikiStorageRepo()); err != nil {
410409
log.Error("SyncMirrors [repo: %-v]: %v", m.Repo, err)
411410
}
412411
}

0 commit comments

Comments
 (0)