Skip to content

Commit f5f58ff

Browse files
committed
Use git.HOME_PATH for Git HOME directory (go-gitea#20114)
Before, in go-gitea#19732, the old home directory is not correct. This PR introduces a new config option for git home: git.HOME_PATH, which is default to %(APP_DATA_PATH)/home And pass env GNUPGHOME to git command, force Gitea to use a stable GNUPGHOME directory
1 parent 039a602 commit f5f58ff

File tree

8 files changed

+63
-27
lines changed

8 files changed

+63
-27
lines changed

custom/conf/app.example.ini

+4-1
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,10 @@ ROUTER = console
617617
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
618618
;;
619619
;; The path of git executable. If empty, Gitea searches through the PATH environment.
620-
PATH =
620+
;PATH =
621+
;;
622+
;; The HOME directory for Git
623+
;HOME_PATH = %(APP_DATA_PATH)/home
621624
;;
622625
;; Disables highlight of added and removed changes
623626
;DISABLE_DIFF_HIGHLIGHT = false

docs/content/doc/advanced/config-cheat-sheet.en-us.md

+2
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,8 @@ Default templates for project boards:
947947
## Git (`git`)
948948

949949
- `PATH`: **""**: The path of Git executable. If empty, Gitea searches through the PATH environment.
950+
- `HOME_PATH`: **%(APP_DATA_PATH)/home**: The HOME directory for Git.
951+
This directory will be used to contain the `.gitconfig` and possible `.gnupg` directories that Gitea's git calls will use. If you can confirm Gitea is the only application running in this environment, you can set it to the normal home directory for Gitea user.
950952
- `DISABLE_DIFF_HIGHLIGHT`: **false**: Disables highlight of added and removed changes.
951953
- `MAX_GIT_DIFF_LINES`: **1000**: Max number of lines allowed of a single file in diff view.
952954
- `MAX_GIT_DIFF_LINE_CHARACTERS`: **5000**: Max character count per line highlighted in diff view.

docs/content/doc/advanced/signing.en-us.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,11 @@ repositories, `SIGNING_KEY=default` could be used to provide different
9797
signing keys on a per-repository basis. However, this is clearly not an
9898
ideal UI and therefore subject to change.
9999

100-
**Since 1.17**, Gitea runs git in its own home directory `[repository].ROOT` and uses its own config `{[repository].ROOT}/.gitconfig`.
100+
**Since 1.17**, Gitea runs git in its own home directory `[git].HOME_PATH` (default to `%(APP_DATA_PATH)/home`)
101+
and uses its own config `{[git].HOME_PATH}/.gitconfig`.
101102
If you have your own customized git config for Gitea, you should set these configs in system git config (aka `/etc/gitconfig`)
102-
or the Gitea internal git config `{[repository].ROOT}/.gitconfig`.
103-
Related home files for git command (like `.gnupg`) should also be put in Gitea's git home directory `[repository].ROOT`.
103+
or the Gitea internal git config `{[git].HOME_PATH}/.gitconfig`.
104+
Related home files for git command (like `.gnupg`) should also be put in Gitea's git home directory `[git].HOME_PATH`.
104105

105106

106107
### `INITIAL_COMMIT`

models/unittest/testdb.go

+2
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ func MainTest(m *testing.M, testOpts *TestOptions) {
107107

108108
setting.Packages.Storage.Path = filepath.Join(setting.AppDataPath, "packages")
109109

110+
setting.Git.HomePath = filepath.Join(setting.AppDataPath, "home")
111+
110112
if err = storage.Init(); err != nil {
111113
fatalTestError("storage.Init: %v\n", err)
112114
}

modules/git/command.go

+23-10
Original file line numberDiff line numberDiff line change
@@ -105,23 +105,36 @@ type RunOpts struct {
105105
PipelineFunc func(context.Context, context.CancelFunc) error
106106
}
107107

108-
// CommonGitCmdEnvs returns the common environment variables for a "git" command.
109-
func CommonGitCmdEnvs() []string {
108+
func commonBaseEnvs() []string {
110109
// at the moment, do not set "GIT_CONFIG_NOSYSTEM", users may have put some configs like "receive.certNonceSeed" in it
111-
return []string{
112-
fmt.Sprintf("LC_ALL=%s", DefaultLocale),
113-
"GIT_TERMINAL_PROMPT=0", // avoid prompting for credentials interactively, supported since git v2.3
114-
"GIT_NO_REPLACE_OBJECTS=1", // ignore replace references (https://git-scm.com/docs/git-replace)
110+
envs := []string{
115111
"HOME=" + HomeDir(), // make Gitea use internal git config only, to prevent conflicts with user's git config
112+
"GIT_NO_REPLACE_OBJECTS=1", // ignore replace references (https://git-scm.com/docs/git-replace)
113+
}
114+
115+
// some environment variables should be passed to git command
116+
passThroughEnvKeys := []string{
117+
"GNUPGHOME", // git may call gnupg to do commit signing
118+
}
119+
for _, key := range passThroughEnvKeys {
120+
if val, ok := os.LookupEnv(key); ok {
121+
envs = append(envs, key+"="+val)
122+
}
116123
}
124+
return envs
125+
}
126+
127+
// CommonGitCmdEnvs returns the common environment variables for a "git" command.
128+
func CommonGitCmdEnvs() []string {
129+
return append(commonBaseEnvs(), []string{
130+
"LC_ALL=" + DefaultLocale,
131+
"GIT_TERMINAL_PROMPT=0", // avoid prompting for credentials interactively, supported since git v2.3
132+
}...)
117133
}
118134

119135
// CommonCmdServEnvs is like CommonGitCmdEnvs but it only returns minimal required environment variables for the "gitea serv" command
120136
func CommonCmdServEnvs() []string {
121-
return []string{
122-
"GIT_NO_REPLACE_OBJECTS=1", // ignore replace references (https://git-scm.com/docs/git-replace)
123-
"HOME=" + HomeDir(), // make Gitea use internal git config only, to prevent conflicts with user's git config
124-
}
137+
return commonBaseEnvs()
125138
}
126139

127140
// Run runs the command with the RunOpts

modules/git/git.go

+13-9
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"fmt"
1212
"os"
1313
"os/exec"
14+
"path/filepath"
1415
"regexp"
1516
"runtime"
1617
"strings"
@@ -19,7 +20,6 @@ import (
1920

2021
"code.gitea.io/gitea/modules/log"
2122
"code.gitea.io/gitea/modules/setting"
22-
2323
"github.com/hashicorp/go-version"
2424
)
2525

@@ -126,8 +126,8 @@ func VersionInfo() string {
126126
}
127127

128128
func checkInit() error {
129-
if setting.RepoRootPath == "" {
130-
return errors.New("can not init Git's HomeDir (RepoRootPath is empty), the setting and git modules are not initialized correctly")
129+
if setting.Git.HomePath == "" {
130+
return errors.New("unable to init Git's HomeDir, incorrect initialization of the setting and git modules")
131131
}
132132
if DefaultContext != nil {
133133
log.Warn("git module has been initialized already, duplicate init should be fixed")
@@ -137,14 +137,14 @@ func checkInit() error {
137137

138138
// HomeDir is the home dir for git to store the global config file used by Gitea internally
139139
func HomeDir() string {
140-
if setting.RepoRootPath == "" {
140+
if setting.Git.HomePath == "" {
141141
// strict check, make sure the git module is initialized correctly.
142142
// attention: when the git module is called in gitea sub-command (serv/hook), the log module is not able to show messages to users.
143143
// for example: if there is gitea git hook code calling git.NewCommand before git.InitXxx, the integration test won't show the real failure reasons.
144-
log.Fatal("can not get Git's HomeDir (RepoRootPath is empty), the setting and git modules are not initialized correctly")
144+
log.Fatal("Unable to init Git's HomeDir, incorrect initialization of the setting and git modules")
145145
return ""
146146
}
147-
return setting.RepoRootPath
147+
return setting.Git.HomePath
148148
}
149149

150150
// InitSimple initializes git module with a very simple step, no config changes, no global command arguments.
@@ -175,11 +175,15 @@ func InitOnceWithSync(ctx context.Context) (err error) {
175175
}
176176

177177
initOnce.Do(func() {
178-
err = InitSimple(ctx)
179-
if err != nil {
178+
if err = InitSimple(ctx); err != nil {
180179
return
181180
}
182181

182+
// when git works with gnupg (commit signing), there should be a stable home for gnupg commands
183+
if _, ok := os.LookupEnv("GNUPGHOME"); !ok {
184+
_ = os.Setenv("GNUPGHOME", filepath.Join(HomeDir(), ".gnupg"))
185+
}
186+
183187
// Since git wire protocol has been released from git v2.18
184188
if setting.Git.EnableAutoGitWireProtocol && CheckGitVersionAtLeast("2.18") == nil {
185189
globalCommandArgs = append(globalCommandArgs, "-c", "protocol.version=2")
@@ -206,7 +210,7 @@ func InitOnceWithSync(ctx context.Context) (err error) {
206210
// syncGitConfig only modifies gitconfig, won't change global variables (otherwise there will be data-race problem)
207211
func syncGitConfig() (err error) {
208212
if err = os.MkdirAll(HomeDir(), os.ModePerm); err != nil {
209-
return fmt.Errorf("unable to create directory %s, err: %w", setting.RepoRootPath, err)
213+
return fmt.Errorf("unable to prepare git home directory %s, err: %w", HomeDir(), err)
210214
}
211215

212216
// Git requires setting user.name and user.email in order to commit changes - old comment: "if they're not set just add some defaults"

modules/git/git_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ import (
2121
func testRun(m *testing.M) error {
2222
_ = log.NewLogger(1000, "console", "console", `{"level":"trace","stacktracelevel":"NONE","stderr":true}`)
2323

24-
repoRootPath, err := os.MkdirTemp(os.TempDir(), "repos")
24+
gitHomePath, err := os.MkdirTemp(os.TempDir(), "git-home")
2525
if err != nil {
2626
return fmt.Errorf("unable to create temp dir: %w", err)
2727
}
28-
defer util.RemoveAll(repoRootPath)
29-
setting.RepoRootPath = repoRootPath
28+
defer util.RemoveAll(gitHomePath)
29+
setting.Git.HomePath = gitHomePath
3030

3131
if err = InitOnceWithSync(context.Background()); err != nil {
3232
return fmt.Errorf("failed to call Init: %w", err)

modules/setting/git.go

+12-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package setting
66

77
import (
8+
"path/filepath"
89
"time"
910

1011
"code.gitea.io/gitea/modules/log"
@@ -13,6 +14,7 @@ import (
1314
// Git settings
1415
var Git = struct {
1516
Path string
17+
HomePath string
1618
DisableDiffHighlight bool
1719
MaxGitDiffLines int
1820
MaxGitDiffLineCharacters int
@@ -67,7 +69,16 @@ var Git = struct {
6769
}
6870

6971
func newGit() {
70-
if err := Cfg.Section("git").MapTo(&Git); err != nil {
72+
sec := Cfg.Section("git")
73+
74+
if err := sec.MapTo(&Git); err != nil {
7175
log.Fatal("Failed to map Git settings: %v", err)
7276
}
77+
78+
Git.HomePath = sec.Key("HOME_PATH").MustString("home")
79+
if !filepath.IsAbs(Git.HomePath) {
80+
Git.HomePath = filepath.Join(AppDataPath, Git.HomePath)
81+
} else {
82+
Git.HomePath = filepath.Clean(Git.HomePath)
83+
}
7384
}

0 commit comments

Comments
 (0)