diff options
Diffstat (limited to 'modules/git/git.go')
-rw-r--r-- | modules/git/git.go | 73 |
1 files changed, 48 insertions, 25 deletions
diff --git a/modules/git/git.go b/modules/git/git.go index 43901b3c1..3a3663995 100644 --- a/modules/git/git.go +++ b/modules/git/git.go @@ -7,35 +7,31 @@ package git import ( "context" + "errors" "fmt" "os" "os/exec" - "path/filepath" "runtime" "strings" "sync" "time" - //"code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "github.com/hashicorp/go-version" ) -var ( - // GitVersionRequired is the minimum Git version required - // At the moment, all code for git 1.x are not changed, if some users want to test with old git client - // or bypass the check, they still have a chance to edit this variable manually. - // If everything works fine, the code for git 1.x could be removed in a separate PR before 1.17 frozen. - GitVersionRequired = "2.0.0" +// GitVersionRequired is the minimum Git version required +const GitVersionRequired = "2.0.0" +var ( // GitExecutable is the command name of git // Could be updated to an absolute path while initialization GitExecutable = "git" - // DefaultContext is the default context to run git commands in - // will be overwritten by InitXxx with HammerContext - DefaultContext = context.Background() + // DefaultContext is the default context to run git commands in, must be initialized by git.InitXxx + DefaultContext context.Context // SupportProcReceive version >= 2.29.0 SupportProcReceive bool @@ -128,36 +124,43 @@ func VersionInfo() string { return fmt.Sprintf(format, args...) } +func checkInit() error { + if setting.RepoRootPath == "" { + return errors.New("can not init Git's HomeDir (RepoRootPath is empty), the setting and git modules are not initialized correctly") + } + if DefaultContext != nil { + log.Warn("git module has been initialized already, duplicate init should be fixed") + } + return nil +} + // HomeDir is the home dir for git to store the global config file used by Gitea internally func HomeDir() string { if setting.RepoRootPath == "" { - // TODO: now, some unit test code call the git module directly without initialization, which is incorrect. - // at the moment, we just use a temp HomeDir to prevent from conflicting with user's git config - // in the future, the git module should be initialized first before use. - tmpHomeDir := filepath.Join(os.TempDir(), "gitea-temp-home") - //log.Error("Git's HomeDir is empty (RepoRootPath is empty), the git module is not initialized correctly, using a temp HomeDir (%s) temporarily", tmpHomeDir) - return tmpHomeDir + // 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. + // 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") + return "" } return setting.RepoRootPath } // InitSimple initializes git module with a very simple step, no config changes, no global command arguments. // This method doesn't change anything to filesystem. At the moment, it is only used by "git serv" sub-command, no data-race +// However, in integration test, the sub-command function may be called in the current process, so the InitSimple would be called multiple times, too func InitSimple(ctx context.Context) error { + if err := checkInit(); err != nil { + return err + } + DefaultContext = ctx if setting.Git.Timeout.Default > 0 { defaultCommandExecutionTimeout = time.Duration(setting.Git.Timeout.Default) * time.Second } - if err := SetExecutablePath(setting.Git.Path); err != nil { - return err - } - - // force cleanup args - globalCommandArgs = []string{} - - return nil + return SetExecutablePath(setting.Git.Path) } var initOnce sync.Once @@ -166,6 +169,10 @@ var initOnce sync.Once // This method will update the global variables ONLY ONCE (just like git.CheckLFSVersion -- which is not ideal too), // otherwise there will be data-race problem at the moment. func InitOnceWithSync(ctx context.Context) (err error) { + if err = checkInit(); err != nil { + return err + } + initOnce.Do(func() { err = InitSimple(ctx) if err != nil { @@ -231,6 +238,9 @@ func syncGitConfig() (err error) { if err := configSet("gc.writeCommitGraph", "true"); err != nil { return err } + if err := configSet("fetch.writeCommitGraph", "true"); err != nil { + return err + } } if SupportProcReceive { @@ -244,6 +254,19 @@ func syncGitConfig() (err error) { } } + // Due to CVE-2022-24765, git now denies access to git directories which are not owned by current user + // however, some docker users and samba users find it difficult to configure their systems so that Gitea's git repositories are owned by the Gitea user. (Possibly Windows Service users - but ownership in this case should really be set correctly on the filesystem.) + // see issue: https://github.com/go-gitea/gitea/issues/19455 + // Fundamentally the problem lies with the uid-gid-mapping mechanism for filesystems in docker on windows (and to a lesser extent samba). + // Docker's configuration mechanism for local filesystems provides no way of setting this mapping and although there is a mechanism for setting this uid through using cifs mounting it is complicated and essentially undocumented + // Thus the owner uid/gid for files on these filesystems will be marked as root. + // As Gitea now always use its internal git config file, and access to the git repositories is managed through Gitea, + // it is now safe to set "safe.directory=*" for internal usage only. + // Please note: the wildcard "*" is only supported by Git 2.30.4/2.31.3/2.32.2/2.33.3/2.34.3/2.35.3/2.36 and later + // Although only supported by Git 2.30.4/2.31.3/2.32.2/2.33.3/2.34.3/2.35.3/2.36 and later - this setting is tolerated by earlier versions + if err := configAddNonExist("safe.directory", "*"); err != nil { + return err + } if runtime.GOOS == "windows" { if err := configSet("core.longpaths", "true"); err != nil { return err |