Skip to content

Commit 41da811

Browse files
authored
Merge branch 'main' into fix-rerun-failed-job-workflow-run-status
2 parents 401b501 + a7eceb5 commit 41da811

File tree

17 files changed

+191
-151
lines changed

17 files changed

+191
-151
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: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ package repo
77
import (
88
"context"
99
"fmt"
10-
"path/filepath"
1110
"strings"
1211

1312
user_model "code.gitea.io/gitea/models/user"
@@ -76,12 +75,12 @@ func (repo *Repository) WikiCloneLink(ctx context.Context, doer *user_model.User
7675
return repo.cloneLink(ctx, doer, repo.Name+".wiki")
7776
}
7877

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")
78+
func RelativeWikiPath(ownerName, repoName string) string {
79+
return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".wiki.git"
8280
}
8381

84-
// WikiPath returns wiki data path for given repository.
85-
func (repo *Repository) WikiPath() string {
86-
return WikiPath(repo.OwnerName, repo.Name)
82+
// WikiStorageRepo returns the storage repo for the wiki
83+
// The wiki repository should have the same object format as the code repository
84+
func (repo *Repository) WikiStorageRepo() StorageRepo {
85+
return StorageRepo(RelativeWikiPath(repo.OwnerName, repo.Name))
8786
}

models/repo/wiki_test.go

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@
44
package repo_test
55

66
import (
7-
"path/filepath"
87
"testing"
98

109
repo_model "code.gitea.io/gitea/models/repo"
1110
"code.gitea.io/gitea/models/unittest"
12-
"code.gitea.io/gitea/modules/setting"
1311

1412
"github.com/stretchr/testify/assert"
1513
)
@@ -23,15 +21,10 @@ func TestRepository_WikiCloneLink(t *testing.T) {
2321
assert.Equal(t, "https://try.gitea.io/user2/repo1.wiki.git", cloneLink.HTTPS)
2422
}
2523

26-
func TestWikiPath(t *testing.T) {
24+
func TestRepository_RelativeWikiPath(t *testing.T) {
2725
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-
}
3126

32-
func TestRepository_WikiPath(t *testing.T) {
33-
assert.NoError(t, unittest.PrepareTestDatabase())
3427
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
35-
expected := filepath.Join(setting.RepoRootPath, "user2/repo1.wiki.git")
36-
assert.Equal(t, expected, repo.WikiPath())
28+
assert.Equal(t, "user2/repo1.wiki.git", repo_model.RelativeWikiPath(repo.OwnerName, repo.Name))
29+
assert.Equal(t, "user2/repo1.wiki.git", repo.WikiStorageRepo().RelativePath())
3730
}

modules/git/key.go

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@
33

44
package git
55

6-
import "code.gitea.io/gitea/modules/setting"
6+
import (
7+
"context"
8+
"strings"
9+
10+
"code.gitea.io/gitea/modules/git/gitcmd"
11+
"code.gitea.io/gitea/modules/setting"
12+
)
713

814
// Based on https://git-scm.com/docs/git-config#Documentation/git-config.txt-gpgformat
915
const (
@@ -24,3 +30,48 @@ func (s *SigningKey) String() string {
2430
setting.PanicInDevOrTesting("don't call SigningKey.String() - it exposes the KeyID which might be a local file path")
2531
return "SigningKey:" + s.Format
2632
}
33+
34+
// GetSigningKey returns the KeyID and git Signature for the repo
35+
func GetSigningKey(ctx context.Context, repoPath string) (*SigningKey, *Signature) {
36+
if setting.Repository.Signing.SigningKey == "none" {
37+
return nil, nil
38+
}
39+
40+
if setting.Repository.Signing.SigningKey == "default" || setting.Repository.Signing.SigningKey == "" {
41+
// Can ignore the error here as it means that commit.gpgsign is not set
42+
value, _, _ := gitcmd.NewCommand("config", "--get", "commit.gpgsign").WithDir(repoPath).RunStdString(ctx)
43+
sign, valid := ParseBool(strings.TrimSpace(value))
44+
if !sign || !valid {
45+
return nil, nil
46+
}
47+
48+
format, _, _ := gitcmd.NewCommand("config", "--default", SigningKeyFormatOpenPGP, "--get", "gpg.format").WithDir(repoPath).RunStdString(ctx)
49+
signingKey, _, _ := gitcmd.NewCommand("config", "--get", "user.signingkey").WithDir(repoPath).RunStdString(ctx)
50+
signingName, _, _ := gitcmd.NewCommand("config", "--get", "user.name").WithDir(repoPath).RunStdString(ctx)
51+
signingEmail, _, _ := gitcmd.NewCommand("config", "--get", "user.email").WithDir(repoPath).RunStdString(ctx)
52+
53+
if strings.TrimSpace(signingKey) == "" {
54+
return nil, nil
55+
}
56+
57+
return &SigningKey{
58+
KeyID: strings.TrimSpace(signingKey),
59+
Format: strings.TrimSpace(format),
60+
}, &Signature{
61+
Name: strings.TrimSpace(signingName),
62+
Email: strings.TrimSpace(signingEmail),
63+
}
64+
}
65+
66+
if setting.Repository.Signing.SigningKey == "" {
67+
return nil, nil
68+
}
69+
70+
return &SigningKey{
71+
KeyID: setting.Repository.Signing.SigningKey,
72+
Format: setting.Repository.Signing.SigningFormat,
73+
}, &Signature{
74+
Name: setting.Repository.Signing.SigningName,
75+
Email: setting.Repository.Signing.SigningEmail,
76+
}
77+
}

modules/gitrepo/clone.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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+
// CloneExternalRepo clones an external repository to the managed repository.
13+
func CloneExternalRepo(ctx context.Context, fromRemoteURL string, toRepo Repository, opts git.CloneRepoOptions) error {
14+
return git.Clone(ctx, fromRemoteURL, repoPath(toRepo), opts)
15+
}
16+
17+
// CloneRepoToLocal clones a managed repository to a local path.
18+
func CloneRepoToLocal(ctx context.Context, fromRepo Repository, toLocalPath string, opts git.CloneRepoOptions) error {
19+
return git.Clone(ctx, repoPath(fromRepo), toLocalPath, opts)
20+
}

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: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@ import (
77
"context"
88
"fmt"
99
"io"
10+
"io/fs"
11+
"os"
1012
"path/filepath"
1113

1214
"code.gitea.io/gitea/modules/git"
15+
"code.gitea.io/gitea/modules/git/gitcmd"
1316
"code.gitea.io/gitea/modules/reqctx"
1417
"code.gitea.io/gitea/modules/setting"
1518
"code.gitea.io/gitea/modules/util"
@@ -86,3 +89,12 @@ func RenameRepository(ctx context.Context, repo, newRepo Repository) error {
8689
func InitRepository(ctx context.Context, repo Repository, objectFormatName string) error {
8790
return git.InitRepository(ctx, repoPath(repo), true, objectFormatName)
8891
}
92+
93+
func UpdateServerInfo(ctx context.Context, repo Repository) error {
94+
_, _, err := RunCmdBytes(ctx, repo, gitcmd.NewCommand("update-server-info"))
95+
return err
96+
}
97+
98+
func GetRepoFS(repo Repository) fs.FS {
99+
return os.DirFS(repoPath(repo))
100+
}

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+
}

modules/gitrepo/signing.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 GetSigningKey(ctx context.Context, repo Repository) (*git.SigningKey, *git.Signature) {
13+
return git.GetSigningKey(ctx, repoPath(repo))
14+
}

routers/web/repo/githttp.go

Lines changed: 17 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ package repo
77
import (
88
"bytes"
99
"compress/gzip"
10-
gocontext "context"
1110
"fmt"
1211
"net/http"
1312
"os"
14-
"path/filepath"
13+
"path"
1514
"regexp"
1615
"slices"
1716
"strconv"
@@ -27,6 +26,7 @@ import (
2726
"code.gitea.io/gitea/models/unit"
2827
"code.gitea.io/gitea/modules/git"
2928
"code.gitea.io/gitea/modules/git/gitcmd"
29+
"code.gitea.io/gitea/modules/gitrepo"
3030
"code.gitea.io/gitea/modules/log"
3131
repo_module "code.gitea.io/gitea/modules/repository"
3232
"code.gitea.io/gitea/modules/setting"
@@ -342,11 +342,11 @@ type serviceHandler struct {
342342
environ []string
343343
}
344344

345-
func (h *serviceHandler) getRepoDir() string {
345+
func (h *serviceHandler) getStorageRepo() gitrepo.Repository {
346346
if h.isWiki {
347-
return h.repo.WikiPath()
347+
return h.repo.WikiStorageRepo()
348348
}
349-
return h.repo.RepoPath()
349+
return h.repo
350350
}
351351

352352
func setHeaderNoCache(ctx *context.Context) {
@@ -378,19 +378,10 @@ func (h *serviceHandler) sendFile(ctx *context.Context, contentType, file string
378378
ctx.Resp.WriteHeader(http.StatusBadRequest)
379379
return
380380
}
381-
reqFile := filepath.Join(h.getRepoDir(), filepath.Clean(file))
382-
383-
fi, err := os.Stat(reqFile)
384-
if os.IsNotExist(err) {
385-
ctx.Resp.WriteHeader(http.StatusNotFound)
386-
return
387-
}
388381

382+
fs := gitrepo.GetRepoFS(h.getStorageRepo())
389383
ctx.Resp.Header().Set("Content-Type", contentType)
390-
ctx.Resp.Header().Set("Content-Length", strconv.FormatInt(fi.Size(), 10))
391-
// http.TimeFormat required a UTC time, refer to https://pkg.go.dev/net/http#TimeFormat
392-
ctx.Resp.Header().Set("Last-Modified", fi.ModTime().UTC().Format(http.TimeFormat))
393-
http.ServeFile(ctx.Resp, ctx.Req, reqFile)
384+
http.ServeFileFS(ctx.Resp, ctx.Req, fs, path.Clean(file))
394385
}
395386

396387
// one or more key=value pairs separated by colons
@@ -416,13 +407,15 @@ func serviceRPC(ctx *context.Context, h *serviceHandler, service string) {
416407
expectedContentType := fmt.Sprintf("application/x-git-%s-request", service)
417408
if ctx.Req.Header.Get("Content-Type") != expectedContentType {
418409
log.Error("Content-Type (%q) doesn't match expected: %q", ctx.Req.Header.Get("Content-Type"), expectedContentType)
410+
// FIXME: why it's 401 if the content type is unexpected?
419411
ctx.Resp.WriteHeader(http.StatusUnauthorized)
420412
return
421413
}
422414

423415
cmd, err := prepareGitCmdWithAllowedService(service)
424416
if err != nil {
425417
log.Error("Failed to prepareGitCmdWithService: %v", err)
418+
// FIXME: why it's 401 if the service type doesn't supported?
426419
ctx.Resp.WriteHeader(http.StatusUnauthorized)
427420
return
428421
}
@@ -449,17 +442,14 @@ func serviceRPC(ctx *context.Context, h *serviceHandler, service string) {
449442
}
450443

451444
var stderr bytes.Buffer
452-
if err := cmd.AddArguments("--stateless-rpc").
453-
AddDynamicArguments(h.getRepoDir()).
454-
WithDir(h.getRepoDir()).
445+
if err := gitrepo.RunCmd(ctx, h.getStorageRepo(), cmd.AddArguments("--stateless-rpc", ".").
455446
WithEnv(append(os.Environ(), h.environ...)).
456447
WithStderr(&stderr).
457448
WithStdin(reqBody).
458449
WithStdout(ctx.Resp).
459-
WithUseContextTimeout(true).
460-
Run(ctx); err != nil {
450+
WithUseContextTimeout(true)); err != nil {
461451
if !git.IsErrCanceledOrKilled(err) {
462-
log.Error("Fail to serve RPC(%s) in %s: %v - %s", service, h.getRepoDir(), err, stderr.String())
452+
log.Error("Fail to serve RPC(%s) in %s: %v - %s", service, h.getStorageRepo().RelativePath(), err, stderr.String())
463453
}
464454
return
465455
}
@@ -496,14 +486,6 @@ func getServiceType(ctx *context.Context) string {
496486
return ""
497487
}
498488

499-
func updateServerInfo(ctx gocontext.Context, dir string) []byte {
500-
out, _, err := gitcmd.NewCommand("update-server-info").WithDir(dir).RunStdBytes(ctx)
501-
if err != nil {
502-
log.Error(fmt.Sprintf("%v - %s", err, string(out)))
503-
}
504-
return out
505-
}
506-
507489
func packetWrite(str string) []byte {
508490
s := strconv.FormatInt(int64(len(str)+4), 16)
509491
if len(s)%4 != 0 {
@@ -527,10 +509,8 @@ func GetInfoRefs(ctx *context.Context) {
527509
}
528510
h.environ = append(os.Environ(), h.environ...)
529511

530-
refs, _, err := cmd.AddArguments("--stateless-rpc", "--advertise-refs", ".").
531-
WithEnv(h.environ).
532-
WithDir(h.getRepoDir()).
533-
RunStdBytes(ctx)
512+
refs, _, err := gitrepo.RunCmdBytes(ctx, h.getStorageRepo(), cmd.AddArguments("--stateless-rpc", "--advertise-refs", ".").
513+
WithEnv(h.environ))
534514
if err != nil {
535515
log.Error(fmt.Sprintf("%v - %s", err, string(refs)))
536516
}
@@ -541,7 +521,9 @@ func GetInfoRefs(ctx *context.Context) {
541521
_, _ = ctx.Resp.Write([]byte("0000"))
542522
_, _ = ctx.Resp.Write(refs)
543523
} else {
544-
updateServerInfo(ctx, h.getRepoDir())
524+
if err := gitrepo.UpdateServerInfo(ctx, h.getStorageRepo()); err != nil {
525+
log.Error("Failed to update server info: %v", err)
526+
}
545527
h.sendFile(ctx, "text/plain; charset=utf-8", "info/refs")
546528
}
547529
}

0 commit comments

Comments
 (0)