aboutsummaryrefslogtreecommitdiffstats
path: root/modules/git
diff options
context:
space:
mode:
authorwxiaoguang <wxiaoguang@gmail.com>2022-06-10 09:57:49 +0800
committerGitHub <noreply@github.com>2022-06-10 09:57:49 +0800
commita0051634b982608d94399033a8b76e7e3b1537ac (patch)
tree174bf860eb23c80bff16dc0e94f8d7d1a3437f0a /modules/git
parente26f84a9b75f250f951e0efa5c5c62860b3c8370 (diff)
downloadgitea-a0051634b982608d94399033a8b76e7e3b1537ac.tar.gz
gitea-a0051634b982608d94399033a8b76e7e3b1537ac.zip
Refactor git module, make Gitea use internal git config (#19732)
* Refactor git module, make Gitea use internal git config, add safe.directory config * introduce git.InitSimple and git.InitWithConfigSync, make serv cmd use gitconfig * use HOME instead of GIT_CONFIG_GLOBAL, because git always needs a correct HOME * fix cmd env in cmd/serv.go * fine tune error message * Fix a incorrect test case * fix configAddNonExist * fix configAddNonExist logic, add `--fixed-value` flag, add tests * add configSetNonExist function in case it's needed. * use configSetNonExist for `user.name` and `user.email` * add some comments * Update cmd/serv.go Co-authored-by: zeripath <art27@cantab.net> * Update cmd/serv.go Co-authored-by: zeripath <art27@cantab.net> * Update modules/git/git.go Co-authored-by: zeripath <art27@cantab.net> * Update modules/setting/setting.go Co-authored-by: zeripath <art27@cantab.net> * Update modules/git/repo_attribute.go Co-authored-by: zeripath <art27@cantab.net> * fix spaces in messages * use `configSet("core.protectNTFS", ...)` instead of `globalCommandArgs` * remove GIT_CONFIG_NOSYSTEM, continue to use system's git config * Update cmd/serv.go Co-authored-by: zeripath <art27@cantab.net> * fix merge * remove code for safe.directory * separate git.CommonEnvs to CommonGitCmdEnvs and CommonCmdServEnvs * avoid Golang's data race error Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Diffstat (limited to 'modules/git')
-rw-r--r--modules/git/command.go40
-rw-r--r--modules/git/commit.go5
-rw-r--r--modules/git/git.go229
-rw-r--r--modules/git/git_test.go67
-rw-r--r--modules/git/lfs.go6
-rw-r--r--modules/git/remote.go4
-rw-r--r--modules/git/repo_attribute.go7
-rw-r--r--modules/git/repo_tree.go8
8 files changed, 229 insertions, 137 deletions
diff --git a/modules/git/command.go b/modules/git/command.go
index f6344dbfd1..d71497f1d7 100644
--- a/modules/git/command.go
+++ b/modules/git/command.go
@@ -8,6 +8,7 @@ package git
import (
"bytes"
"context"
+ "errors"
"fmt"
"io"
"os"
@@ -104,6 +105,25 @@ type RunOpts struct {
PipelineFunc func(context.Context, context.CancelFunc) error
}
+// CommonGitCmdEnvs returns the common environment variables for a "git" command.
+func CommonGitCmdEnvs() []string {
+ // at the moment, do not set "GIT_CONFIG_NOSYSTEM", users may have put some configs like "receive.certNonceSeed" in it
+ return []string{
+ fmt.Sprintf("LC_ALL=%s", DefaultLocale),
+ "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
+func CommonCmdServEnvs() []string {
+ return []string{
+ "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
func (c *Command) Run(opts *RunOpts) error {
if opts == nil {
@@ -148,16 +168,8 @@ func (c *Command) Run(opts *RunOpts) error {
cmd.Env = opts.Env
}
- cmd.Env = append(
- cmd.Env,
- fmt.Sprintf("LC_ALL=%s", DefaultLocale),
- // avoid prompting for credentials interactively, supported since git v2.3
- "GIT_TERMINAL_PROMPT=0",
- // ignore replace references (https://git-scm.com/docs/git-replace)
- "GIT_NO_REPLACE_OBJECTS=1",
- )
-
process.SetSysProcAttribute(cmd)
+ cmd.Env = append(cmd.Env, CommonGitCmdEnvs()...)
cmd.Dir = opts.Dir
cmd.Stdout = opts.Stdout
cmd.Stderr = opts.Stderr
@@ -184,7 +196,9 @@ func (c *Command) Run(opts *RunOpts) error {
type RunStdError interface {
error
+ Unwrap() error
Stderr() string
+ IsExitCode(code int) bool
}
type runStdError struct {
@@ -209,6 +223,14 @@ func (r *runStdError) Stderr() string {
return r.stderr
}
+func (r *runStdError) IsExitCode(code int) bool {
+ var exitError *exec.ExitError
+ if errors.As(r.err, &exitError) {
+ return exitError.ExitCode() == code
+ }
+ return false
+}
+
func bytesToString(b []byte) string {
return *(*string)(unsafe.Pointer(&b)) // that's what Golang's strings.Builder.String() does (go/src/strings/builder.go)
}
diff --git a/modules/git/commit.go b/modules/git/commit.go
index 8c194ef502..99fbbd0cfc 100644
--- a/modules/git/commit.go
+++ b/modules/git/commit.go
@@ -398,11 +398,6 @@ func (c *Commit) GetSubModule(entryname string) (*SubModule, error) {
// GetBranchName gets the closest branch name (as returned by 'git name-rev --name-only')
func (c *Commit) GetBranchName() (string, error) {
- err := LoadGitVersion()
- if err != nil {
- return "", fmt.Errorf("Git version missing: %v", err)
- }
-
args := []string{
"name-rev",
}
diff --git a/modules/git/git.go b/modules/git/git.go
index 8fad070330..5817bd2c7f 100644
--- a/modules/git/git.go
+++ b/modules/git/git.go
@@ -10,11 +10,13 @@ import (
"fmt"
"os"
"os/exec"
+ "path/filepath"
"runtime"
"strings"
+ "sync"
"time"
- "code.gitea.io/gitea/modules/process"
+ "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"github.com/hashicorp/go-version"
@@ -32,38 +34,33 @@ var (
GitExecutable = "git"
// DefaultContext is the default context to run git commands in
- // will be overwritten by Init with HammerContext
+ // will be overwritten by InitWithConfigSync with HammerContext
DefaultContext = context.Background()
- gitVersion *version.Version
-
// SupportProcReceive version >= 2.29.0
SupportProcReceive bool
-)
-// LocalVersion returns current Git version from shell.
-func LocalVersion() (*version.Version, error) {
- if err := LoadGitVersion(); err != nil {
- return nil, err
- }
- return gitVersion, nil
-}
+ // initMutex is used to avoid Golang's data race error. see the comments below.
+ initMutex sync.Mutex
+
+ gitVersion *version.Version
+)
-// LoadGitVersion returns current Git version from shell.
-func LoadGitVersion() error {
+// loadGitVersion returns current Git version from shell. Internal usage only.
+func loadGitVersion() (*version.Version, error) {
// doesn't need RWMutex because its exec by Init()
if gitVersion != nil {
- return nil
+ return gitVersion, nil
}
- stdout, _, runErr := NewCommand(context.Background(), "version").RunStdString(nil)
+ stdout, _, runErr := NewCommand(DefaultContext, "version").RunStdString(nil)
if runErr != nil {
- return runErr
+ return nil, runErr
}
fields := strings.Fields(stdout)
if len(fields) < 3 {
- return fmt.Errorf("not enough output: %s", stdout)
+ return nil, fmt.Errorf("invalid git version output: %s", stdout)
}
var versionString string
@@ -78,7 +75,7 @@ func LoadGitVersion() error {
var err error
gitVersion, err = version.NewVersion(versionString)
- return err
+ return gitVersion, err
}
// SetExecutablePath changes the path of git executable and checks the file permission and version.
@@ -93,7 +90,7 @@ func SetExecutablePath(path string) error {
}
GitExecutable = absPath
- err = LoadGitVersion()
+ _, err = loadGitVersion()
if err != nil {
return fmt.Errorf("unable to load git version: %w", err)
}
@@ -120,7 +117,10 @@ func SetExecutablePath(path string) error {
// VersionInfo returns git version information
func VersionInfo() string {
- format := "Git Version: %s"
+ if gitVersion == nil {
+ return "(git not found)"
+ }
+ format := "%s"
args := []interface{}{gitVersion.Original()}
// Since git wire protocol has been released from git v2.18
if setting.Git.EnableAutoGitWireProtocol && CheckGitVersionAtLeast("2.18") == nil {
@@ -131,8 +131,33 @@ func VersionInfo() string {
return fmt.Sprintf(format, args...)
}
-// Init initializes git module
-func Init(ctx context.Context) error {
+// InitSimple initializes git module with a very simple step, no config changes, no global command arguments.
+// This method doesn't change anything to filesystem
+func InitSimple(ctx context.Context) error {
+ initMutex.Lock()
+ defer initMutex.Unlock()
+
+ return initSimpleInternal(ctx)
+}
+
+// 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
+ }
+ return setting.RepoRootPath
+}
+
+func initSimpleInternal(ctx context.Context) error {
+ // at the moment, when running integration tests, the git.InitXxx would be called twice.
+ // one is called by the GlobalInitInstalled, one is called by TestMain.
+ // so the init functions should be protected by a mutex to avoid Golang's data race error.
+
DefaultContext = ctx
if setting.Git.Timeout.Default > 0 {
@@ -146,6 +171,23 @@ func Init(ctx context.Context) error {
// force cleanup args
globalCommandArgs = []string{}
+ return nil
+}
+
+// InitWithConfigSync initializes git module. This method may create directories or write files into filesystem
+func InitWithConfigSync(ctx context.Context) error {
+ initMutex.Lock()
+ defer initMutex.Unlock()
+
+ err := initSimpleInternal(ctx)
+ if err != nil {
+ return err
+ }
+
+ if err = os.MkdirAll(setting.RepoRootPath, os.ModePerm); err != nil {
+ return fmt.Errorf("unable to create directory %s, err: %w", setting.RepoRootPath, err)
+ }
+
if CheckGitVersionAtLeast("2.9") == nil {
// Explicitly disable credential helper, otherwise Git credentials might leak
globalCommandArgs = append(globalCommandArgs, "-c", "credential.helper=")
@@ -161,68 +203,71 @@ func Init(ctx context.Context) error {
globalCommandArgs = append(globalCommandArgs, "-c", "uploadpack.allowfilter=true", "-c", "uploadpack.allowAnySHA1InWant=true")
}
- // Save current git version on init to gitVersion otherwise it would require an RWMutex
- if err := LoadGitVersion(); err != nil {
- return err
- }
-
- // Git requires setting user.name and user.email in order to commit changes - if they're not set just add some defaults
- for configKey, defaultValue := range map[string]string{"user.name": "Gitea", "user.email": "gitea@fake.local"} {
- if err := checkAndSetConfig(configKey, defaultValue, false); err != nil {
+ // Git requires setting user.name and user.email in order to commit changes - old comment: "if they're not set just add some defaults"
+ // TODO: need to confirm whether users really need to change these values manually. It seems that these values are dummy only and not really used.
+ // If these values are not really used, then they can be set (overwritten) directly without considering about existence.
+ for configKey, defaultValue := range map[string]string{
+ "user.name": "Gitea",
+ "user.email": "gitea@fake.local",
+ } {
+ if err := configSetNonExist(configKey, defaultValue); err != nil {
return err
}
}
// Set git some configurations - these must be set to these values for gitea to work correctly
- if err := checkAndSetConfig("core.quotePath", "false", true); err != nil {
+ if err := configSet("core.quotePath", "false"); err != nil {
return err
}
if CheckGitVersionAtLeast("2.10") == nil {
- if err := checkAndSetConfig("receive.advertisePushOptions", "true", true); err != nil {
+ if err := configSet("receive.advertisePushOptions", "true"); err != nil {
return err
}
}
if CheckGitVersionAtLeast("2.18") == nil {
- if err := checkAndSetConfig("core.commitGraph", "true", true); err != nil {
+ if err := configSet("core.commitGraph", "true"); err != nil {
return err
}
- if err := checkAndSetConfig("gc.writeCommitGraph", "true", true); err != nil {
+ if err := configSet("gc.writeCommitGraph", "true"); err != nil {
return err
}
}
if CheckGitVersionAtLeast("2.29") == nil {
// set support for AGit flow
- if err := checkAndAddConfig("receive.procReceiveRefs", "refs/for"); err != nil {
+ if err := configAddNonExist("receive.procReceiveRefs", "refs/for"); err != nil {
return err
}
SupportProcReceive = true
} else {
- if err := checkAndRemoveConfig("receive.procReceiveRefs", "refs/for"); err != nil {
+ if err := configUnsetAll("receive.procReceiveRefs", "refs/for"); err != nil {
return err
}
SupportProcReceive = false
}
if runtime.GOOS == "windows" {
- if err := checkAndSetConfig("core.longpaths", "true", true); err != nil {
+ if err := configSet("core.longpaths", "true"); err != nil {
return err
}
- }
- if setting.Git.DisableCoreProtectNTFS {
- if err := checkAndSetConfig("core.protectntfs", "false", true); err != nil {
+ if setting.Git.DisableCoreProtectNTFS {
+ err = configSet("core.protectNTFS", "false")
+ } else {
+ err = configUnsetAll("core.protectNTFS", "false")
+ }
+ if err != nil {
return err
}
- globalCommandArgs = append(globalCommandArgs, "-c", "core.protectntfs=false")
}
+
return nil
}
// CheckGitVersionAtLeast check git version is at least the constraint version
func CheckGitVersionAtLeast(atLeast string) error {
- if err := LoadGitVersion(); err != nil {
+ if _, err := loadGitVersion(); err != nil {
return err
}
atLeastVersion, err := version.NewVersion(atLeast)
@@ -235,75 +280,75 @@ func CheckGitVersionAtLeast(atLeast string) error {
return nil
}
-func checkAndSetConfig(key, defaultValue string, forceToDefault bool) error {
- stdout, stderr, err := process.GetManager().Exec("git.Init(get setting)", GitExecutable, "config", "--get", key)
- if err != nil {
- perr, ok := err.(*process.Error)
- if !ok {
- return fmt.Errorf("Failed to get git %s(%v) errType %T: %s", key, err, err, stderr)
- }
- eerr, ok := perr.Err.(*exec.ExitError)
- if !ok || eerr.ExitCode() != 1 {
- return fmt.Errorf("Failed to get git %s(%v) errType %T: %s", key, err, err, stderr)
- }
+func configSet(key, value string) error {
+ stdout, _, err := NewCommand(DefaultContext, "config", "--get", key).RunStdString(nil)
+ if err != nil && !err.IsExitCode(1) {
+ return fmt.Errorf("failed to get git config %s, err: %w", key, err)
}
currValue := strings.TrimSpace(stdout)
-
- if currValue == defaultValue || (!forceToDefault && len(currValue) > 0) {
+ if currValue == value {
return nil
}
- if _, stderr, err = process.GetManager().Exec(fmt.Sprintf("git.Init(set %s)", key), "git", "config", "--global", key, defaultValue); err != nil {
- return fmt.Errorf("Failed to set git %s(%s): %s", key, err, stderr)
+ _, _, err = NewCommand(DefaultContext, "config", "--global", key, value).RunStdString(nil)
+ if err != nil {
+ return fmt.Errorf("failed to set git global config %s, err: %w", key, err)
}
return nil
}
-func checkAndAddConfig(key, value string) error {
- _, stderr, err := process.GetManager().Exec("git.Init(get setting)", GitExecutable, "config", "--get", key, value)
- if err != nil {
- perr, ok := err.(*process.Error)
- if !ok {
- return fmt.Errorf("Failed to get git %s(%v) errType %T: %s", key, err, err, stderr)
- }
- eerr, ok := perr.Err.(*exec.ExitError)
- if !ok || eerr.ExitCode() != 1 {
- return fmt.Errorf("Failed to get git %s(%v) errType %T: %s", key, err, err, stderr)
- }
- if eerr.ExitCode() == 1 {
- if _, stderr, err = process.GetManager().Exec(fmt.Sprintf("git.Init(set %s)", key), "git", "config", "--global", "--add", key, value); err != nil {
- return fmt.Errorf("Failed to set git %s(%s): %s", key, err, stderr)
- }
- return nil
+func configSetNonExist(key, value string) error {
+ _, _, err := NewCommand(DefaultContext, "config", "--get", key).RunStdString(nil)
+ if err == nil {
+ // already exist
+ return nil
+ }
+ if err.IsExitCode(1) {
+ // not exist, set new config
+ _, _, err = NewCommand(DefaultContext, "config", "--global", key, value).RunStdString(nil)
+ if err != nil {
+ return fmt.Errorf("failed to set git global config %s, err: %w", key, err)
}
+ return nil
}
- return nil
+ return fmt.Errorf("failed to get git config %s, err: %w", key, err)
}
-func checkAndRemoveConfig(key, value string) error {
- _, stderr, err := process.GetManager().Exec("git.Init(get setting)", GitExecutable, "config", "--get", key, value)
- if err != nil {
- perr, ok := err.(*process.Error)
- if !ok {
- return fmt.Errorf("Failed to get git %s(%v) errType %T: %s", key, err, err, stderr)
- }
- eerr, ok := perr.Err.(*exec.ExitError)
- if !ok || eerr.ExitCode() != 1 {
- return fmt.Errorf("Failed to get git %s(%v) errType %T: %s", key, err, err, stderr)
- }
- if eerr.ExitCode() == 1 {
- return nil
+func configAddNonExist(key, value string) error {
+ _, _, err := NewCommand(DefaultContext, "config", "--fixed-value", "--get", key, value).RunStdString(nil)
+ if err == nil {
+ // already exist
+ return nil
+ }
+ if err.IsExitCode(1) {
+ // not exist, add new config
+ _, _, err = NewCommand(DefaultContext, "config", "--global", "--add", key, value).RunStdString(nil)
+ if err != nil {
+ return fmt.Errorf("failed to add git global config %s, err: %w", key, err)
}
+ return nil
}
+ return fmt.Errorf("failed to get git config %s, err: %w", key, err)
+}
- if _, stderr, err = process.GetManager().Exec(fmt.Sprintf("git.Init(set %s)", key), "git", "config", "--global", "--unset-all", key, value); err != nil {
- return fmt.Errorf("Failed to set git %s(%s): %s", key, err, stderr)
+func configUnsetAll(key, value string) error {
+ _, _, err := NewCommand(DefaultContext, "config", "--get", key).RunStdString(nil)
+ if err == nil {
+ // exist, need to remove
+ _, _, err = NewCommand(DefaultContext, "config", "--global", "--fixed-value", "--unset-all", key, value).RunStdString(nil)
+ if err != nil {
+ return fmt.Errorf("failed to unset git global config %s, err: %w", key, err)
+ }
+ return nil
}
-
- return nil
+ if err.IsExitCode(1) {
+ // not exist
+ return nil
+ }
+ return fmt.Errorf("failed to get git config %s, err: %w", key, err)
}
// Fsck verifies the connectivity and validity of the objects in the database
diff --git a/modules/git/git_test.go b/modules/git/git_test.go
index c62a55badc..5b1cd820e8 100644
--- a/modules/git/git_test.go
+++ b/modules/git/git_test.go
@@ -8,23 +8,74 @@ import (
"context"
"fmt"
"os"
+ "strings"
"testing"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/util"
+
+ "github.com/stretchr/testify/assert"
)
-func fatalTestError(fmtStr string, args ...interface{}) {
- fmt.Fprintf(os.Stderr, fmtStr, args...)
- os.Exit(1)
+func testRun(m *testing.M) error {
+ _ = log.NewLogger(1000, "console", "console", `{"level":"trace","stacktracelevel":"NONE","stderr":true}`)
+
+ repoRootPath, err := os.MkdirTemp(os.TempDir(), "repos")
+ if err != nil {
+ return fmt.Errorf("unable to create temp dir: %w", err)
+ }
+ defer util.RemoveAll(repoRootPath)
+ setting.RepoRootPath = repoRootPath
+
+ if err = InitWithConfigSync(context.Background()); err != nil {
+ return fmt.Errorf("failed to call Init: %w", err)
+ }
+
+ exitCode := m.Run()
+ if exitCode != 0 {
+ return fmt.Errorf("run test failed, ExitCode=%d", exitCode)
+ }
+ return nil
}
func TestMain(m *testing.M) {
- _ = log.NewLogger(1000, "console", "console", `{"level":"trace","stacktracelevel":"NONE","stderr":true}`)
+ if err := testRun(m); err != nil {
+ _, _ = fmt.Fprintf(os.Stderr, "Test failed: %v", err)
+ os.Exit(1)
+ }
+}
- if err := Init(context.Background()); err != nil {
- fatalTestError("Init failed: %v", err)
+func TestGitConfig(t *testing.T) {
+ gitConfigContains := func(sub string) bool {
+ if b, err := os.ReadFile(HomeDir() + "/.gitconfig"); err == nil {
+ return strings.Contains(string(b), sub)
+ }
+ return false
}
- exitStatus := m.Run()
- os.Exit(exitStatus)
+ assert.False(t, gitConfigContains("key-a"))
+
+ assert.NoError(t, configSetNonExist("test.key-a", "val-a"))
+ assert.True(t, gitConfigContains("key-a = val-a"))
+
+ assert.NoError(t, configSetNonExist("test.key-a", "val-a-changed"))
+ assert.False(t, gitConfigContains("key-a = val-a-changed"))
+
+ assert.NoError(t, configSet("test.key-a", "val-a-changed"))
+ assert.True(t, gitConfigContains("key-a = val-a-changed"))
+
+ assert.NoError(t, configAddNonExist("test.key-b", "val-b"))
+ assert.True(t, gitConfigContains("key-b = val-b"))
+
+ assert.NoError(t, configAddNonExist("test.key-b", "val-2b"))
+ assert.True(t, gitConfigContains("key-b = val-b"))
+ assert.True(t, gitConfigContains("key-b = val-2b"))
+
+ assert.NoError(t, configUnsetAll("test.key-b", "val-b"))
+ assert.False(t, gitConfigContains("key-b = val-b"))
+ assert.True(t, gitConfigContains("key-b = val-2b"))
+
+ assert.NoError(t, configUnsetAll("test.key-b", "val-2b"))
+ assert.False(t, gitConfigContains("key-b = val-2b"))
}
diff --git a/modules/git/lfs.go b/modules/git/lfs.go
index cdd9d15b2e..c5d8354b6d 100644
--- a/modules/git/lfs.go
+++ b/modules/git/lfs.go
@@ -18,12 +18,6 @@ func CheckLFSVersion() {
if setting.LFS.StartServer {
// Disable LFS client hooks if installed for the current OS user
// Needs at least git v2.1.2
-
- err := LoadGitVersion()
- if err != nil {
- logger.Fatal("Error retrieving git version: %v", err)
- }
-
if CheckGitVersionAtLeast("2.1.2") != nil {
setting.LFS.StartServer = false
logger.Error("LFS server support needs at least Git v2.1.2")
diff --git a/modules/git/remote.go b/modules/git/remote.go
index 536b1681ce..b2a2e6d7ab 100644
--- a/modules/git/remote.go
+++ b/modules/git/remote.go
@@ -11,10 +11,6 @@ import (
// GetRemoteAddress returns the url of a specific remote of the repository.
func GetRemoteAddress(ctx context.Context, repoPath, remoteName string) (*url.URL, error) {
- err := LoadGitVersion()
- if err != nil {
- return nil, err
- }
var cmd *Command
if CheckGitVersionAtLeast("2.7") == nil {
cmd = NewCommand(ctx, "remote", "get-url", remoteName)
diff --git a/modules/git/repo_attribute.go b/modules/git/repo_attribute.go
index a18c80c3f1..38818788f3 100644
--- a/modules/git/repo_attribute.go
+++ b/modules/git/repo_attribute.go
@@ -28,11 +28,6 @@ type CheckAttributeOpts struct {
// CheckAttribute return the Blame object of file
func (repo *Repository) CheckAttribute(opts CheckAttributeOpts) (map[string]map[string]string, error) {
- err := LoadGitVersion()
- if err != nil {
- return nil, fmt.Errorf("git version missing: %v", err)
- }
-
env := []string{}
if len(opts.IndexFile) > 0 && CheckGitVersionAtLeast("1.7.8") == nil {
@@ -126,7 +121,7 @@ type CheckAttributeReader struct {
cancel context.CancelFunc
}
-// Init initializes the cmd
+// Init initializes the CheckAttributeReader
func (c *CheckAttributeReader) Init(ctx context.Context) error {
cmdArgs := []string{"check-attr", "--stdin", "-z"}
diff --git a/modules/git/repo_tree.go b/modules/git/repo_tree.go
index 3e7a9c2cfb..2e139daddf 100644
--- a/modules/git/repo_tree.go
+++ b/modules/git/repo_tree.go
@@ -24,11 +24,6 @@ type CommitTreeOpts struct {
// CommitTree creates a commit from a given tree id for the user with provided message
func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opts CommitTreeOpts) (SHA1, error) {
- err := LoadGitVersion()
- if err != nil {
- return SHA1{}, err
- }
-
commitTimeStr := time.Now().Format(time.RFC3339)
// Because this may call hooks we should pass in the environment
@@ -60,14 +55,13 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt
stdout := new(bytes.Buffer)
stderr := new(bytes.Buffer)
- err = cmd.Run(&RunOpts{
+ err := cmd.Run(&RunOpts{
Env: env,
Dir: repo.Path,
Stdin: messageBytes,
Stdout: stdout,
Stderr: stderr,
})
-
if err != nil {
return SHA1{}, ConcatenateError(err, stderr.String())
}