From dec3c8cd388fb14cbefdce104e3cd8fe0981ddd5 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 12 Dec 2025 09:37:31 -0800 Subject: [PATCH 1/4] Remove unreleased support of signing key in the repository git configuration file --- modules/git/commit.go | 8 -------- modules/git/{repo_gpg.go => gpg.go} | 21 ++++++++------------- modules/git/key.go | 12 ++++++------ modules/git/repo_base_nogogit.go | 2 -- modules/gitrepo/signing.go | 4 ++-- routers/api/v1/misc/signing.go | 6 +----- routers/web/repo/setting/setting.go | 4 ++-- services/asymkey/commit.go | 2 +- services/asymkey/sign.go | 24 ++++++++++++------------ services/context/repo.go | 2 +- services/repository/files/patch.go | 2 +- services/repository/files/temp_repo.go | 4 ++-- services/repository/files/update.go | 2 +- services/repository/init.go | 2 +- 14 files changed, 38 insertions(+), 57 deletions(-) rename modules/git/{repo_gpg.go => gpg.go} (63%) diff --git a/modules/git/commit.go b/modules/git/commit.go index af09697018..1917a72bbf 100644 --- a/modules/git/commit.go +++ b/modules/git/commit.go @@ -323,14 +323,6 @@ func GetFullCommitID(ctx context.Context, repoPath, shortID string) (string, err return strings.TrimSpace(commitID), nil } -// GetRepositoryDefaultPublicGPGKey returns the default public key for this commit -func (c *Commit) GetRepositoryDefaultPublicGPGKey(forceUpdate bool) (*GPGSettings, error) { - if c.repo == nil { - return nil, nil - } - return c.repo.GetDefaultPublicGPGKey(forceUpdate) -} - func IsStringLikelyCommitID(objFmt ObjectFormat, s string, minLength ...int) bool { maxLen := 64 // sha256 if objFmt != nil { diff --git a/modules/git/repo_gpg.go b/modules/git/gpg.go similarity index 63% rename from modules/git/repo_gpg.go rename to modules/git/gpg.go index eb1e71e30a..94a0015d72 100644 --- a/modules/git/repo_gpg.go +++ b/modules/git/gpg.go @@ -5,6 +5,7 @@ package git import ( + "context" "fmt" "os" "strings" @@ -34,38 +35,32 @@ func (gpgSettings *GPGSettings) LoadPublicKeyContent() error { } // GetDefaultPublicGPGKey will return and cache the default public GPG settings for this repository -func (repo *Repository) GetDefaultPublicGPGKey(forceUpdate bool) (*GPGSettings, error) { - if repo.gpgSettings != nil && !forceUpdate { - return repo.gpgSettings, nil - } - +func GetDefaultPublicGPGKey(ctx context.Context, forceUpdate bool) (*GPGSettings, error) { gpgSettings := &GPGSettings{ Sign: true, } - value, _, _ := gitcmd.NewCommand("config", "--get", "commit.gpgsign").WithDir(repo.Path).RunStdString(repo.Ctx) + value, _, _ := gitcmd.NewCommand("config", "--global", "--get", "commit.gpgsign").RunStdString(ctx) sign, valid := ParseBool(strings.TrimSpace(value)) if !sign || !valid { gpgSettings.Sign = false - repo.gpgSettings = gpgSettings return gpgSettings, nil } - signingKey, _, _ := gitcmd.NewCommand("config", "--get", "user.signingkey").WithDir(repo.Path).RunStdString(repo.Ctx) + signingKey, _, _ := gitcmd.NewCommand("config", "--global", "--get", "user.signingkey").RunStdString(ctx) gpgSettings.KeyID = strings.TrimSpace(signingKey) - format, _, _ := gitcmd.NewCommand("config", "--default", SigningKeyFormatOpenPGP, "--get", "gpg.format").WithDir(repo.Path).RunStdString(repo.Ctx) + format, _, _ := gitcmd.NewCommand("config", "--global", "--default", SigningKeyFormatOpenPGP, "--get", "gpg.format").RunStdString(ctx) gpgSettings.Format = strings.TrimSpace(format) - defaultEmail, _, _ := gitcmd.NewCommand("config", "--get", "user.email").WithDir(repo.Path).RunStdString(repo.Ctx) + defaultEmail, _, _ := gitcmd.NewCommand("config", "--global", "--get", "user.email").RunStdString(ctx) gpgSettings.Email = strings.TrimSpace(defaultEmail) - defaultName, _, _ := gitcmd.NewCommand("config", "--get", "user.name").WithDir(repo.Path).RunStdString(repo.Ctx) + defaultName, _, _ := gitcmd.NewCommand("config", "--global", "--get", "user.name").RunStdString(ctx) gpgSettings.Name = strings.TrimSpace(defaultName) if err := gpgSettings.LoadPublicKeyContent(); err != nil { return nil, err } - repo.gpgSettings = gpgSettings - return repo.gpgSettings, nil + return gpgSettings, nil } diff --git a/modules/git/key.go b/modules/git/key.go index 39e79ddbe0..9d51704595 100644 --- a/modules/git/key.go +++ b/modules/git/key.go @@ -32,23 +32,23 @@ func (s *SigningKey) String() string { } // GetSigningKey returns the KeyID and git Signature for the repo -func GetSigningKey(ctx context.Context, repoPath string) (*SigningKey, *Signature) { +func GetSigningKey(ctx context.Context) (*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) + value, _, _ := gitcmd.NewCommand("config", "--global", "--get", "commit.gpgsign").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) + format, _, _ := gitcmd.NewCommand("config", "--global", "--default", SigningKeyFormatOpenPGP, "--get", "gpg.format").RunStdString(ctx) + signingKey, _, _ := gitcmd.NewCommand("config", "--global", "--get", "user.signingkey").RunStdString(ctx) + signingName, _, _ := gitcmd.NewCommand("config", "--global", "--get", "user.name").RunStdString(ctx) + signingEmail, _, _ := gitcmd.NewCommand("config", "--global", "--get", "user.email").RunStdString(ctx) if strings.TrimSpace(signingKey) == "" { return nil, nil diff --git a/modules/git/repo_base_nogogit.go b/modules/git/repo_base_nogogit.go index 4091e70846..17c71da5ef 100644 --- a/modules/git/repo_base_nogogit.go +++ b/modules/git/repo_base_nogogit.go @@ -23,8 +23,6 @@ type Repository struct { tagCache *ObjectCache[*Tag] - gpgSettings *GPGSettings - batchInUse bool batch *Batch diff --git a/modules/gitrepo/signing.go b/modules/gitrepo/signing.go index c50978d15a..2f77758d8c 100644 --- a/modules/gitrepo/signing.go +++ b/modules/gitrepo/signing.go @@ -9,6 +9,6 @@ import ( "code.gitea.io/gitea/modules/git" ) -func GetSigningKey(ctx context.Context, repo Repository) (*git.SigningKey, *git.Signature) { - return git.GetSigningKey(ctx, repoPath(repo)) +func GetSigningKey(ctx context.Context) (*git.SigningKey, *git.Signature) { + return git.GetSigningKey(ctx) } diff --git a/routers/api/v1/misc/signing.go b/routers/api/v1/misc/signing.go index db70e04b8f..fd1d6e724e 100644 --- a/routers/api/v1/misc/signing.go +++ b/routers/api/v1/misc/signing.go @@ -12,11 +12,7 @@ import ( func getSigningKey(ctx *context.APIContext, expectedFormat string) { // if the handler is in the repo's route group, get the repo's signing key // otherwise, get the global signing key - path := "" - if ctx.Repo != nil && ctx.Repo.Repository != nil { - path = ctx.Repo.Repository.RepoPath() - } - content, format, err := asymkey_service.PublicSigningKey(ctx, path) + content, format, err := asymkey_service.PublicSigningKey(ctx) if err != nil { ctx.APIErrorInternal(err) return diff --git a/routers/web/repo/setting/setting.go b/routers/web/repo/setting/setting.go index 60eb35f56d..0c73c1490f 100644 --- a/routers/web/repo/setting/setting.go +++ b/routers/web/repo/setting/setting.go @@ -61,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, _ := gitrepo.GetSigningKey(ctx, ctx.Repo.Repository) + signing, _ := gitrepo.GetSigningKey(ctx) ctx.Data["SigningKeyAvailable"] = signing != nil ctx.Data["SigningSettings"] = setting.Repository.Signing ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled @@ -104,7 +104,7 @@ func SettingsPost(ctx *context.Context) { ctx.Data["DefaultMirrorInterval"] = setting.Mirror.DefaultInterval ctx.Data["MinimumMirrorInterval"] = setting.Mirror.MinInterval - signing, _ := gitrepo.GetSigningKey(ctx, ctx.Repo.Repository) + signing, _ := gitrepo.GetSigningKey(ctx) ctx.Data["SigningKeyAvailable"] = signing != nil ctx.Data["SigningSettings"] = setting.Repository.Signing ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled diff --git a/services/asymkey/commit.go b/services/asymkey/commit.go index 54ef052a50..6286588a60 100644 --- a/services/asymkey/commit.go +++ b/services/asymkey/commit.go @@ -162,7 +162,7 @@ func parseCommitWithGPGSignature(ctx context.Context, c *git.Commit, committer * } } - defaultGPGSettings, err := c.GetRepositoryDefaultPublicGPGKey(false) + defaultGPGSettings, err := git.GetDefaultPublicGPGKey(ctx, false) if err != nil { log.Error("Error getting default public gpg key: %v", err) } else if defaultGPGSettings == nil { diff --git a/services/asymkey/sign.go b/services/asymkey/sign.go index 1ed05ba287..f2a1797d49 100644 --- a/services/asymkey/sign.go +++ b/services/asymkey/sign.go @@ -108,34 +108,34 @@ func IsErrWontSign(err error) bool { return ok } -// PublicSigningKey gets the public signing key within a provided repository directory -func PublicSigningKey(ctx context.Context, repoPath string) (content, format string, err error) { - signingKey, _ := git.GetSigningKey(ctx, repoPath) +// PublicSigningKey gets the public signing key +func PublicSigningKey(ctx context.Context) (content, format string, err error) { + signingKey, _ := git.GetSigningKey(ctx) if signingKey == nil { return "", "", nil } if signingKey.Format == git.SigningKeyFormatSSH { content, err := os.ReadFile(signingKey.KeyID) if err != nil { - log.Error("Unable to read SSH public key file in %s: %s, %v", repoPath, signingKey, err) + log.Error("Unable to read SSH public key file: %s, %v", signingKey, err) return "", signingKey.Format, err } return string(content), signingKey.Format, nil } - content, stderr, err := process.GetManager().ExecDir(ctx, -1, repoPath, + content, stderr, err := process.GetManager().ExecDir(ctx, -1, setting.Git.HomePath, "gpg --export -a", "gpg", "--export", "-a", signingKey.KeyID) if err != nil { - log.Error("Unable to get default signing key in %s: %s, %s, %v", repoPath, signingKey, stderr, err) + log.Error("Unable to get default signing key: %s, %s, %v", signingKey, stderr, err) return "", signingKey.Format, err } return content, signingKey.Format, nil } // 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) { +func SignInitialCommit(ctx context.Context, u *user_model.User) (bool, *git.SigningKey, *git.Signature, error) { rules := signingModeFromStrings(setting.Repository.Signing.InitialCommit) - signingKey, sig := git.GetSigningKey(ctx, repoPath) + signingKey, sig := git.GetSigningKey(ctx) if signingKey == nil { return false, nil, nil, &ErrWontSign{noKey} } @@ -171,7 +171,7 @@ 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) { rules := signingModeFromStrings(setting.Repository.Signing.Wiki) - signingKey, sig := gitrepo.GetSigningKey(ctx, repo.WikiStorageRepo()) + signingKey, sig := gitrepo.GetSigningKey(ctx) if signingKey == nil { return false, nil, nil, &ErrWontSign{noKey} } @@ -222,9 +222,9 @@ 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) { +func SignCRUDAction(ctx context.Context, u *user_model.User, tmpBasePath, parentCommit string) (bool, *git.SigningKey, *git.Signature, error) { rules := signingModeFromStrings(setting.Repository.Signing.CRUDActions) - signingKey, sig := git.GetSigningKey(ctx, repoPath) + signingKey, sig := git.GetSigningKey(ctx) if signingKey == nil { return false, nil, nil, &ErrWontSign{noKey} } @@ -288,7 +288,7 @@ func SignMerge(ctx context.Context, pr *issues_model.PullRequest, u *user_model. } repo := pr.BaseRepo - signingKey, signer := gitrepo.GetSigningKey(ctx, repo) + signingKey, signer := gitrepo.GetSigningKey(ctx) if signingKey == nil { return false, nil, nil, &ErrWontSign{noKey} } diff --git a/services/context/repo.go b/services/context/repo.go index 64b8695236..331bc69349 100644 --- a/services/context/repo.go +++ b/services/context/repo.go @@ -140,7 +140,7 @@ func PrepareCommitFormOptions(ctx *Context, doer *user_model.User, targetRepo *r protectionRequireSigned = protectedBranch.RequireSignedCommits } - willSign, signKey, _, err := asymkey_service.SignCRUDAction(ctx, targetRepo.RepoPath(), doer, targetRepo.RepoPath(), refName.String()) + willSign, signKey, _, err := asymkey_service.SignCRUDAction(ctx, doer, targetRepo.RepoPath(), refName.String()) wontSignReason := "" if asymkey_service.IsErrWontSign(err) { wontSignReason = string(err.(*asymkey_service.ErrWontSign).Reason) diff --git a/services/repository/files/patch.go b/services/repository/files/patch.go index 8fe6bb917b..5361091c90 100644 --- a/services/repository/files/patch.go +++ b/services/repository/files/patch.go @@ -95,7 +95,7 @@ func (opts *ApplyDiffPatchOptions) Validate(ctx context.Context, repo *repo_mode } } if protectedBranch != nil && protectedBranch.RequireSignedCommits { - _, _, _, err := asymkey_service.SignCRUDAction(ctx, repo.RepoPath(), doer, repo.RepoPath(), opts.OldBranch) + _, _, _, err := asymkey_service.SignCRUDAction(ctx, doer, repo.RepoPath(), opts.OldBranch) if err != nil { if !asymkey_service.IsErrWontSign(err) { return err diff --git a/services/repository/files/temp_repo.go b/services/repository/files/temp_repo.go index aaf9566aec..cb39abfd6e 100644 --- a/services/repository/files/temp_repo.go +++ b/services/repository/files/temp_repo.go @@ -303,9 +303,9 @@ func (t *TemporaryUploadRepository) CommitTree(ctx context.Context, opts *Commit var key *git.SigningKey var signer *git.Signature if opts.ParentCommitID != "" { - sign, key, signer, _ = asymkey_service.SignCRUDAction(ctx, t.repo.RepoPath(), opts.DoerUser, t.basePath, opts.ParentCommitID) + sign, key, signer, _ = asymkey_service.SignCRUDAction(ctx, opts.DoerUser, t.basePath, opts.ParentCommitID) } else { - sign, key, signer, _ = asymkey_service.SignInitialCommit(ctx, t.repo.RepoPath(), opts.DoerUser) + sign, key, signer, _ = asymkey_service.SignInitialCommit(ctx, opts.DoerUser) } if sign { if key.Format != "" { diff --git a/services/repository/files/update.go b/services/repository/files/update.go index 4830f711fc..967c4d928e 100644 --- a/services/repository/files/update.go +++ b/services/repository/files/update.go @@ -686,7 +686,7 @@ func VerifyBranchProtection(ctx context.Context, repo *repo_model.Repository, do } } if protectedBranch.RequireSignedCommits { - _, _, _, err := asymkey_service.SignCRUDAction(ctx, repo.RepoPath(), doer, repo.RepoPath(), branchName) + _, _, _, err := asymkey_service.SignCRUDAction(ctx, doer, repo.RepoPath(), branchName) if err != nil { if !asymkey_service.IsErrWontSign(err) { return err diff --git a/services/repository/init.go b/services/repository/init.go index 8d9decf811..51cc113d63 100644 --- a/services/repository/init.go +++ b/services/repository/init.go @@ -41,7 +41,7 @@ func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi cmd := gitcmd.NewCommand("commit", "--message=Initial commit"). AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email) - sign, key, signer, _ := asymkey_service.SignInitialCommit(ctx, tmpPath, u) + sign, key, signer, _ := asymkey_service.SignInitialCommit(ctx, u) if sign { if key.Format != "" { cmd.AddConfig("gpg.format", key.Format) From 7ebcb24131c215d28ddc41b01f092dd5096a7b2c Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 12 Dec 2025 09:48:18 -0800 Subject: [PATCH 2/4] Some improvements --- modules/git/gpg.go | 10 ++++++++++ modules/git/repo.go | 10 ---------- modules/git/repo_base_gogit.go | 1 - routers/api/v1/misc/signing.go | 3 +-- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/modules/git/gpg.go b/modules/git/gpg.go index 94a0015d72..38ab749d38 100644 --- a/modules/git/gpg.go +++ b/modules/git/gpg.go @@ -14,6 +14,16 @@ import ( "code.gitea.io/gitea/modules/process" ) +// GPGSettings represents the default GPG settings for this repository +type GPGSettings struct { + Sign bool + KeyID string + Email string + Name string + PublicKeyContent string + Format string +} + // LoadPublicKeyContent will load the key from gpg func (gpgSettings *GPGSettings) LoadPublicKeyContent() error { if gpgSettings.Format == SigningKeyFormatSSH { diff --git a/modules/git/repo.go b/modules/git/repo.go index baf29432ec..579accf92e 100644 --- a/modules/git/repo.go +++ b/modules/git/repo.go @@ -20,16 +20,6 @@ import ( "code.gitea.io/gitea/modules/proxy" ) -// GPGSettings represents the default GPG settings for this repository -type GPGSettings struct { - Sign bool - KeyID string - Email string - Name string - PublicKeyContent string - Format string -} - const prettyLogFormat = `--pretty=format:%H` func (repo *Repository) ShowPrettyFormatLogToList(ctx context.Context, revisionRange string) ([]*Commit, error) { diff --git a/modules/git/repo_base_gogit.go b/modules/git/repo_base_gogit.go index e0d0b45372..986264fd93 100644 --- a/modules/git/repo_base_gogit.go +++ b/modules/git/repo_base_gogit.go @@ -32,7 +32,6 @@ type Repository struct { gogitRepo *gogit.Repository gogitStorage *filesystem.Storage - gpgSettings *GPGSettings Ctx context.Context LastCommitCache *LastCommitCache diff --git a/routers/api/v1/misc/signing.go b/routers/api/v1/misc/signing.go index fd1d6e724e..6e1a9a09b2 100644 --- a/routers/api/v1/misc/signing.go +++ b/routers/api/v1/misc/signing.go @@ -10,8 +10,7 @@ import ( ) func getSigningKey(ctx *context.APIContext, expectedFormat string) { - // if the handler is in the repo's route group, get the repo's signing key - // otherwise, get the global signing key + // get the global signing key content, format, err := asymkey_service.PublicSigningKey(ctx) if err != nil { ctx.APIErrorInternal(err) From e2870aaa881b45bbde49fa9f8f7e0add23797190 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 12 Dec 2025 09:56:53 -0800 Subject: [PATCH 3/4] Add cache back for gpgsetting --- modules/git/gpg.go | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/modules/git/gpg.go b/modules/git/gpg.go index 38ab749d38..c9be30dbf9 100644 --- a/modules/git/gpg.go +++ b/modules/git/gpg.go @@ -9,6 +9,7 @@ import ( "fmt" "os" "strings" + "sync" "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/process" @@ -26,6 +27,10 @@ type GPGSettings struct { // LoadPublicKeyContent will load the key from gpg func (gpgSettings *GPGSettings) LoadPublicKeyContent() error { + if gpgSettings.PublicKeyContent != "" { + return nil + } + if gpgSettings.Format == SigningKeyFormatSSH { content, err := os.ReadFile(gpgSettings.KeyID) if err != nil { @@ -44,33 +49,45 @@ func (gpgSettings *GPGSettings) LoadPublicKeyContent() error { return nil } -// GetDefaultPublicGPGKey will return and cache the default public GPG settings for this repository +var ( + loadPublicGPGKeyMutex sync.Mutex + globalGPGSettings *GPGSettings +) + +// GetDefaultPublicGPGKey will return and cache the default public GPG settings func GetDefaultPublicGPGKey(ctx context.Context, forceUpdate bool) (*GPGSettings, error) { - gpgSettings := &GPGSettings{ + loadPublicGPGKeyMutex.Lock() + defer loadPublicGPGKeyMutex.Unlock() + + if globalGPGSettings != nil && !forceUpdate { + return globalGPGSettings, nil + } + + globalGPGSettings = &GPGSettings{ Sign: true, } value, _, _ := gitcmd.NewCommand("config", "--global", "--get", "commit.gpgsign").RunStdString(ctx) sign, valid := ParseBool(strings.TrimSpace(value)) if !sign || !valid { - gpgSettings.Sign = false - return gpgSettings, nil + globalGPGSettings.Sign = false + return globalGPGSettings, nil } signingKey, _, _ := gitcmd.NewCommand("config", "--global", "--get", "user.signingkey").RunStdString(ctx) - gpgSettings.KeyID = strings.TrimSpace(signingKey) + globalGPGSettings.KeyID = strings.TrimSpace(signingKey) format, _, _ := gitcmd.NewCommand("config", "--global", "--default", SigningKeyFormatOpenPGP, "--get", "gpg.format").RunStdString(ctx) - gpgSettings.Format = strings.TrimSpace(format) + globalGPGSettings.Format = strings.TrimSpace(format) defaultEmail, _, _ := gitcmd.NewCommand("config", "--global", "--get", "user.email").RunStdString(ctx) - gpgSettings.Email = strings.TrimSpace(defaultEmail) + globalGPGSettings.Email = strings.TrimSpace(defaultEmail) defaultName, _, _ := gitcmd.NewCommand("config", "--global", "--get", "user.name").RunStdString(ctx) - gpgSettings.Name = strings.TrimSpace(defaultName) + globalGPGSettings.Name = strings.TrimSpace(defaultName) - if err := gpgSettings.LoadPublicKeyContent(); err != nil { + if err := globalGPGSettings.LoadPublicKeyContent(); err != nil { return nil, err } - return gpgSettings, nil + return globalGPGSettings, nil } From fb475470f024de105e763b506549a6e4088e2035 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 12 Dec 2025 10:06:36 -0800 Subject: [PATCH 4/4] Use RWMutex --- modules/git/gpg.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/modules/git/gpg.go b/modules/git/gpg.go index c9be30dbf9..dbc5569309 100644 --- a/modules/git/gpg.go +++ b/modules/git/gpg.go @@ -50,12 +50,21 @@ func (gpgSettings *GPGSettings) LoadPublicKeyContent() error { } var ( - loadPublicGPGKeyMutex sync.Mutex + loadPublicGPGKeyMutex sync.RWMutex globalGPGSettings *GPGSettings ) // GetDefaultPublicGPGKey will return and cache the default public GPG settings func GetDefaultPublicGPGKey(ctx context.Context, forceUpdate bool) (*GPGSettings, error) { + if !forceUpdate { + loadPublicGPGKeyMutex.RLock() + if globalGPGSettings != nil { + defer loadPublicGPGKeyMutex.RUnlock() + return globalGPGSettings, nil + } + loadPublicGPGKeyMutex.RUnlock() + } + loadPublicGPGKeyMutex.Lock() defer loadPublicGPGKeyMutex.Unlock()