Use git.HOME_PATH for Git HOME directory (#20114)
* Add git.HOME_PATH * add legacy file check * Apply suggestions from code review Co-authored-by: zeripath <art27@cantab.net> * pass env GNUPGHOME to git command, move the existing .gitconfig to new home, make the fix for 1.17rc more clear. * set git.HOME_PATH for docker images to default HOME * Revert "set git.HOME_PATH for docker images to default HOME" This reverts commit f120101ddc267cef74e4f4b92c783d5fc8e275a1. * force Gitea to use a stable GNUPGHOME directory * extra check to ensure only process dir or symlink for legacy files * refactor variable name * The legacy dir check (for 1.17-rc1) could be removed with 1.18 release, since users should have upgraded from 1.17-rc to 1.17-stable * Update modules/git/git.go Co-authored-by: Steven Kriegler <61625851+justusbunsi@users.noreply.github.com> * remove initFixGitHome117rc * Update git.go * Update docs/content/doc/advanced/config-cheat-sheet.en-us.md Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: Steven Kriegler <61625851+justusbunsi@users.noreply.github.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
parent
c273dea508
commit
496b8e3990
8 changed files with 64 additions and 28 deletions
|
@ -603,7 +603,10 @@ ROUTER = console
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
;; The path of git executable. If empty, Gitea searches through the PATH environment.
|
;; The path of git executable. If empty, Gitea searches through the PATH environment.
|
||||||
PATH =
|
;PATH =
|
||||||
|
;;
|
||||||
|
;; The HOME directory for Git
|
||||||
|
;HOME_PATH = %(APP_DATA_PATH)/home
|
||||||
;;
|
;;
|
||||||
;; Disables highlight of added and removed changes
|
;; Disables highlight of added and removed changes
|
||||||
;DISABLE_DIFF_HIGHLIGHT = false
|
;DISABLE_DIFF_HIGHLIGHT = false
|
||||||
|
|
|
@ -948,6 +948,8 @@ Default templates for project boards:
|
||||||
## Git (`git`)
|
## Git (`git`)
|
||||||
|
|
||||||
- `PATH`: **""**: The path of Git executable. If empty, Gitea searches through the PATH environment.
|
- `PATH`: **""**: The path of Git executable. If empty, Gitea searches through the PATH environment.
|
||||||
|
- `HOME_PATH`: **%(APP_DATA_PATH)/home**: The HOME directory for Git.
|
||||||
|
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.
|
||||||
- `DISABLE_DIFF_HIGHLIGHT`: **false**: Disables highlight of added and removed changes.
|
- `DISABLE_DIFF_HIGHLIGHT`: **false**: Disables highlight of added and removed changes.
|
||||||
- `MAX_GIT_DIFF_LINES`: **1000**: Max number of lines allowed of a single file in diff view.
|
- `MAX_GIT_DIFF_LINES`: **1000**: Max number of lines allowed of a single file in diff view.
|
||||||
- `MAX_GIT_DIFF_LINE_CHARACTERS`: **5000**: Max character count per line highlighted in diff view.
|
- `MAX_GIT_DIFF_LINE_CHARACTERS`: **5000**: Max character count per line highlighted in diff view.
|
||||||
|
|
|
@ -97,10 +97,11 @@ repositories, `SIGNING_KEY=default` could be used to provide different
|
||||||
signing keys on a per-repository basis. However, this is clearly not an
|
signing keys on a per-repository basis. However, this is clearly not an
|
||||||
ideal UI and therefore subject to change.
|
ideal UI and therefore subject to change.
|
||||||
|
|
||||||
**Since 1.17**, Gitea runs git in its own home directory `[repository].ROOT` and uses its own config `{[repository].ROOT}/.gitconfig`.
|
**Since 1.17**, Gitea runs git in its own home directory `[git].HOME_PATH` (default to `%(APP_DATA_PATH)/home`)
|
||||||
|
and uses its own config `{[git].HOME_PATH}/.gitconfig`.
|
||||||
If you have your own customized git config for Gitea, you should set these configs in system git config (aka `/etc/gitconfig`)
|
If you have your own customized git config for Gitea, you should set these configs in system git config (aka `/etc/gitconfig`)
|
||||||
or the Gitea internal git config `{[repository].ROOT}/.gitconfig`.
|
or the Gitea internal git config `{[git].HOME_PATH}/.gitconfig`.
|
||||||
Related home files for git command (like `.gnupg`) should also be put in Gitea's git home directory `[repository].ROOT`.
|
Related home files for git command (like `.gnupg`) should also be put in Gitea's git home directory `[git].HOME_PATH`.
|
||||||
|
|
||||||
|
|
||||||
### `INITIAL_COMMIT`
|
### `INITIAL_COMMIT`
|
||||||
|
|
|
@ -107,6 +107,8 @@ func MainTest(m *testing.M, testOpts *TestOptions) {
|
||||||
|
|
||||||
setting.Packages.Storage.Path = filepath.Join(setting.AppDataPath, "packages")
|
setting.Packages.Storage.Path = filepath.Join(setting.AppDataPath, "packages")
|
||||||
|
|
||||||
|
setting.Git.HomePath = filepath.Join(setting.AppDataPath, "home")
|
||||||
|
|
||||||
if err = storage.Init(); err != nil {
|
if err = storage.Init(); err != nil {
|
||||||
fatalTestError("storage.Init: %v\n", err)
|
fatalTestError("storage.Init: %v\n", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,23 +105,36 @@ type RunOpts struct {
|
||||||
PipelineFunc func(context.Context, context.CancelFunc) error
|
PipelineFunc func(context.Context, context.CancelFunc) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func commonBaseEnvs() []string {
|
||||||
|
// at the moment, do not set "GIT_CONFIG_NOSYSTEM", users may have put some configs like "receive.certNonceSeed" in it
|
||||||
|
envs := []string{
|
||||||
|
"HOME=" + HomeDir(), // make Gitea use internal git config only, to prevent conflicts with user's git config
|
||||||
|
"GIT_NO_REPLACE_OBJECTS=1", // ignore replace references (https://git-scm.com/docs/git-replace)
|
||||||
|
}
|
||||||
|
|
||||||
|
// some environment variables should be passed to git command
|
||||||
|
passThroughEnvKeys := []string{
|
||||||
|
"GNUPGHOME", // git may call gnupg to do commit signing
|
||||||
|
}
|
||||||
|
for _, key := range passThroughEnvKeys {
|
||||||
|
if val, ok := os.LookupEnv(key); ok {
|
||||||
|
envs = append(envs, key+"="+val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return envs
|
||||||
|
}
|
||||||
|
|
||||||
// CommonGitCmdEnvs returns the common environment variables for a "git" command.
|
// CommonGitCmdEnvs returns the common environment variables for a "git" command.
|
||||||
func CommonGitCmdEnvs() []string {
|
func CommonGitCmdEnvs() []string {
|
||||||
// at the moment, do not set "GIT_CONFIG_NOSYSTEM", users may have put some configs like "receive.certNonceSeed" in it
|
return append(commonBaseEnvs(), []string{
|
||||||
return []string{
|
"LC_ALL=" + DefaultLocale,
|
||||||
fmt.Sprintf("LC_ALL=%s", DefaultLocale),
|
|
||||||
"GIT_TERMINAL_PROMPT=0", // avoid prompting for credentials interactively, supported since git v2.3
|
"GIT_TERMINAL_PROMPT=0", // avoid prompting for credentials interactively, supported since git v2.3
|
||||||
"GIT_NO_REPLACE_OBJECTS=1", // ignore replace references (https://git-scm.com/docs/git-replace)
|
}...)
|
||||||
"HOME=" + HomeDir(), // make Gitea use internal git config only, to prevent conflicts with user's git config
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommonCmdServEnvs is like CommonGitCmdEnvs but it only returns minimal required environment variables for the "gitea serv" command
|
// CommonCmdServEnvs is like CommonGitCmdEnvs but it only returns minimal required environment variables for the "gitea serv" command
|
||||||
func CommonCmdServEnvs() []string {
|
func CommonCmdServEnvs() []string {
|
||||||
return []string{
|
return commonBaseEnvs()
|
||||||
"GIT_NO_REPLACE_OBJECTS=1", // ignore replace references (https://git-scm.com/docs/git-replace)
|
|
||||||
"HOME=" + HomeDir(), // make Gitea use internal git config only, to prevent conflicts with user's git config
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run runs the command with the RunOpts
|
// Run runs the command with the RunOpts
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -19,7 +20,6 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/hashicorp/go-version"
|
"github.com/hashicorp/go-version"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -126,8 +126,8 @@ func VersionInfo() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkInit() error {
|
func checkInit() error {
|
||||||
if setting.RepoRootPath == "" {
|
if setting.Git.HomePath == "" {
|
||||||
return errors.New("can not init Git's HomeDir (RepoRootPath is empty), the setting and git modules are not initialized correctly")
|
return errors.New("unable to init Git's HomeDir, incorrect initialization of the setting and git modules")
|
||||||
}
|
}
|
||||||
if DefaultContext != nil {
|
if DefaultContext != nil {
|
||||||
log.Warn("git module has been initialized already, duplicate init should be fixed")
|
log.Warn("git module has been initialized already, duplicate init should be fixed")
|
||||||
|
@ -137,14 +137,14 @@ func checkInit() error {
|
||||||
|
|
||||||
// HomeDir is the home dir for git to store the global config file used by Gitea internally
|
// HomeDir is the home dir for git to store the global config file used by Gitea internally
|
||||||
func HomeDir() string {
|
func HomeDir() string {
|
||||||
if setting.RepoRootPath == "" {
|
if setting.Git.HomePath == "" {
|
||||||
// strict check, make sure the git module is initialized correctly.
|
// strict check, make sure the git module is initialized correctly.
|
||||||
// attention: when the git module is called in gitea sub-command (serv/hook), the log module is not able to show messages to users.
|
// attention: when the git module is called in gitea sub-command (serv/hook), the log module is not able to show messages to users.
|
||||||
// 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.
|
// 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.
|
||||||
log.Fatal("can not get Git's HomeDir (RepoRootPath is empty), the setting and git modules are not initialized correctly")
|
log.Fatal("Unable to init Git's HomeDir, incorrect initialization of the setting and git modules")
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return setting.RepoRootPath
|
return setting.Git.HomePath
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitSimple initializes git module with a very simple step, no config changes, no global command arguments.
|
// 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) {
|
||||||
}
|
}
|
||||||
|
|
||||||
initOnce.Do(func() {
|
initOnce.Do(func() {
|
||||||
err = InitSimple(ctx)
|
if err = InitSimple(ctx); err != nil {
|
||||||
if err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// when git works with gnupg (commit signing), there should be a stable home for gnupg commands
|
||||||
|
if _, ok := os.LookupEnv("GNUPGHOME"); !ok {
|
||||||
|
_ = os.Setenv("GNUPGHOME", filepath.Join(HomeDir(), ".gnupg"))
|
||||||
|
}
|
||||||
|
|
||||||
// Since git wire protocol has been released from git v2.18
|
// Since git wire protocol has been released from git v2.18
|
||||||
if setting.Git.EnableAutoGitWireProtocol && CheckGitVersionAtLeast("2.18") == nil {
|
if setting.Git.EnableAutoGitWireProtocol && CheckGitVersionAtLeast("2.18") == nil {
|
||||||
globalCommandArgs = append(globalCommandArgs, "-c", "protocol.version=2")
|
globalCommandArgs = append(globalCommandArgs, "-c", "protocol.version=2")
|
||||||
|
@ -206,7 +210,7 @@ func InitOnceWithSync(ctx context.Context) (err error) {
|
||||||
// syncGitConfig only modifies gitconfig, won't change global variables (otherwise there will be data-race problem)
|
// syncGitConfig only modifies gitconfig, won't change global variables (otherwise there will be data-race problem)
|
||||||
func syncGitConfig() (err error) {
|
func syncGitConfig() (err error) {
|
||||||
if err = os.MkdirAll(HomeDir(), os.ModePerm); err != nil {
|
if err = os.MkdirAll(HomeDir(), os.ModePerm); err != nil {
|
||||||
return fmt.Errorf("unable to create directory %s, err: %w", setting.RepoRootPath, err)
|
return fmt.Errorf("unable to prepare git home directory %s, err: %w", HomeDir(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Git requires setting user.name and user.email in order to commit changes - old comment: "if they're not set just add some defaults"
|
// Git requires setting user.name and user.email in order to commit changes - old comment: "if they're not set just add some defaults"
|
||||||
|
|
|
@ -21,12 +21,12 @@ import (
|
||||||
func testRun(m *testing.M) error {
|
func testRun(m *testing.M) error {
|
||||||
_ = log.NewLogger(1000, "console", "console", `{"level":"trace","stacktracelevel":"NONE","stderr":true}`)
|
_ = log.NewLogger(1000, "console", "console", `{"level":"trace","stacktracelevel":"NONE","stderr":true}`)
|
||||||
|
|
||||||
repoRootPath, err := os.MkdirTemp(os.TempDir(), "repos")
|
gitHomePath, err := os.MkdirTemp(os.TempDir(), "git-home")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to create temp dir: %w", err)
|
return fmt.Errorf("unable to create temp dir: %w", err)
|
||||||
}
|
}
|
||||||
defer util.RemoveAll(repoRootPath)
|
defer util.RemoveAll(gitHomePath)
|
||||||
setting.RepoRootPath = repoRootPath
|
setting.Git.HomePath = gitHomePath
|
||||||
|
|
||||||
if err = InitOnceWithSync(context.Background()); err != nil {
|
if err = InitOnceWithSync(context.Background()); err != nil {
|
||||||
return fmt.Errorf("failed to call Init: %w", err)
|
return fmt.Errorf("failed to call Init: %w", err)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
package setting
|
package setting
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -13,6 +14,7 @@ import (
|
||||||
// Git settings
|
// Git settings
|
||||||
var Git = struct {
|
var Git = struct {
|
||||||
Path string
|
Path string
|
||||||
|
HomePath string
|
||||||
DisableDiffHighlight bool
|
DisableDiffHighlight bool
|
||||||
MaxGitDiffLines int
|
MaxGitDiffLines int
|
||||||
MaxGitDiffLineCharacters int
|
MaxGitDiffLineCharacters int
|
||||||
|
@ -67,7 +69,16 @@ var Git = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newGit() {
|
func newGit() {
|
||||||
if err := Cfg.Section("git").MapTo(&Git); err != nil {
|
sec := Cfg.Section("git")
|
||||||
|
|
||||||
|
if err := sec.MapTo(&Git); err != nil {
|
||||||
log.Fatal("Failed to map Git settings: %v", err)
|
log.Fatal("Failed to map Git settings: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Git.HomePath = sec.Key("HOME_PATH").MustString("home")
|
||||||
|
if !filepath.IsAbs(Git.HomePath) {
|
||||||
|
Git.HomePath = filepath.Join(AppDataPath, Git.HomePath)
|
||||||
|
} else {
|
||||||
|
Git.HomePath = filepath.Clean(Git.HomePath)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue