Skip to content

Commit 1679c76

Browse files
committed
Let git support proxy when necessary
1 parent 2d019b7 commit 1679c76

File tree

14 files changed

+183
-85
lines changed

14 files changed

+183
-85
lines changed

contrib/pr/checkout.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func runPR() {
8080
setting.RunUser = curUser.Username
8181

8282
log.Printf("[PR] Loading fixtures data ...\n")
83-
setting.CheckLFSVersion()
83+
git.CheckLFSVersion()
8484
//models.LoadConfigs()
8585
/*
8686
setting.Database.Type = "sqlite3"

integrations/git_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ func standardCommitAndPushTest(t *testing.T, dstPath string) (little, big string
143143
func lfsCommitAndPushTest(t *testing.T, dstPath string) (littleLFS, bigLFS string) {
144144
t.Run("LFS", func(t *testing.T) {
145145
defer PrintCurrentTest(t)()
146-
setting.CheckLFSVersion()
146+
git.CheckLFSVersion()
147147
if !setting.LFS.StartServer {
148148
t.Skip()
149149
return
@@ -213,7 +213,7 @@ func rawTest(t *testing.T, ctx *APITestContext, little, big, littleLFS, bigLFS s
213213
resp := session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
214214
assert.Equal(t, littleSize, resp.Length)
215215

216-
setting.CheckLFSVersion()
216+
git.CheckLFSVersion()
217217
if setting.LFS.StartServer {
218218
req = NewRequest(t, "GET", path.Join("/", username, reponame, "/raw/branch/master/", littleLFS))
219219
resp := session.MakeRequest(t, req, http.StatusOK)
@@ -255,7 +255,7 @@ func mediaTest(t *testing.T, ctx *APITestContext, little, big, littleLFS, bigLFS
255255
resp := session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
256256
assert.Equal(t, littleSize, resp.Length)
257257

258-
setting.CheckLFSVersion()
258+
git.CheckLFSVersion()
259259
if setting.LFS.StartServer {
260260
req = NewRequest(t, "GET", path.Join("/", username, reponame, "/media/branch/master/", littleLFS))
261261
resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)

integrations/integration_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626

2727
"code.gitea.io/gitea/models"
2828
"code.gitea.io/gitea/modules/base"
29+
"code.gitea.io/gitea/modules/git"
2930
"code.gitea.io/gitea/modules/graceful"
3031
"code.gitea.io/gitea/modules/log"
3132
"code.gitea.io/gitea/modules/queue"
@@ -163,7 +164,7 @@ func initIntegrationTest() {
163164
setting.SetCustomPathAndConf("", "", "")
164165
setting.NewContext()
165166
util.RemoveAll(models.LocalCopyPath())
166-
setting.CheckLFSVersion()
167+
git.CheckLFSVersion()
167168
setting.InitDBConfig()
168169
if err := storage.Init(); err != nil {
169170
fmt.Printf("Init storage failed: %v", err)

integrations/lfs_getobject_test.go

+7-6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"testing"
1414

1515
"code.gitea.io/gitea/models"
16+
"code.gitea.io/gitea/modules/git"
1617
"code.gitea.io/gitea/modules/lfs"
1718
"code.gitea.io/gitea/modules/setting"
1819
"code.gitea.io/gitea/routers/routes"
@@ -90,7 +91,7 @@ func checkResponseTestContentEncoding(t *testing.T, content *[]byte, resp *httpt
9091

9192
func TestGetLFSSmall(t *testing.T) {
9293
defer prepareTestEnv(t)()
93-
setting.CheckLFSVersion()
94+
git.CheckLFSVersion()
9495
if !setting.LFS.StartServer {
9596
t.Skip()
9697
return
@@ -103,7 +104,7 @@ func TestGetLFSSmall(t *testing.T) {
103104

104105
func TestGetLFSLarge(t *testing.T) {
105106
defer prepareTestEnv(t)()
106-
setting.CheckLFSVersion()
107+
git.CheckLFSVersion()
107108
if !setting.LFS.StartServer {
108109
t.Skip()
109110
return
@@ -119,7 +120,7 @@ func TestGetLFSLarge(t *testing.T) {
119120

120121
func TestGetLFSGzip(t *testing.T) {
121122
defer prepareTestEnv(t)()
122-
setting.CheckLFSVersion()
123+
git.CheckLFSVersion()
123124
if !setting.LFS.StartServer {
124125
t.Skip()
125126
return
@@ -140,7 +141,7 @@ func TestGetLFSGzip(t *testing.T) {
140141

141142
func TestGetLFSZip(t *testing.T) {
142143
defer prepareTestEnv(t)()
143-
setting.CheckLFSVersion()
144+
git.CheckLFSVersion()
144145
if !setting.LFS.StartServer {
145146
t.Skip()
146147
return
@@ -163,7 +164,7 @@ func TestGetLFSZip(t *testing.T) {
163164

164165
func TestGetLFSRangeNo(t *testing.T) {
165166
defer prepareTestEnv(t)()
166-
setting.CheckLFSVersion()
167+
git.CheckLFSVersion()
167168
if !setting.LFS.StartServer {
168169
t.Skip()
169170
return
@@ -176,7 +177,7 @@ func TestGetLFSRangeNo(t *testing.T) {
176177

177178
func TestGetLFSRange(t *testing.T) {
178179
defer prepareTestEnv(t)()
179-
setting.CheckLFSVersion()
180+
git.CheckLFSVersion()
180181
if !setting.LFS.StartServer {
181182
t.Skip()
182183
return

integrations/migration-test/migration_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"code.gitea.io/gitea/models/migrations"
2424
"code.gitea.io/gitea/modules/base"
2525
"code.gitea.io/gitea/modules/charset"
26+
"code.gitea.io/gitea/modules/git"
2627
"code.gitea.io/gitea/modules/setting"
2728
"code.gitea.io/gitea/modules/util"
2829

@@ -61,7 +62,7 @@ func initMigrationTest(t *testing.T) func() {
6162
assert.NoError(t, util.RemoveAll(setting.RepoRootPath))
6263
assert.NoError(t, util.CopyDir(path.Join(filepath.Dir(setting.AppPath), "integrations/gitea-repositories-meta"), setting.RepoRootPath))
6364

64-
setting.CheckLFSVersion()
65+
git.CheckLFSVersion()
6566
setting.InitDBConfig()
6667
setting.NewLogServices(true)
6768
return deferFn

models/migrations/migrations_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616

1717
"code.gitea.io/gitea/models"
1818
"code.gitea.io/gitea/modules/base"
19+
"code.gitea.io/gitea/modules/git"
1920
"code.gitea.io/gitea/modules/setting"
2021
"code.gitea.io/gitea/modules/timeutil"
2122
"code.gitea.io/gitea/modules/util"
@@ -55,7 +56,7 @@ func TestMain(m *testing.M) {
5556

5657
setting.SetCustomPathAndConf("", "", "")
5758
setting.NewContext()
58-
setting.CheckLFSVersion()
59+
git.CheckLFSVersion()
5960
setting.InitDBConfig()
6061
setting.NewLogServices(true)
6162

modules/git/command.go

+37-14
Original file line numberDiff line numberDiff line change
@@ -109,48 +109,71 @@ func (c *Command) RunInDirTimeoutEnvFullPipeline(env []string, timeout time.Dura
109109
// RunInDirTimeoutEnvFullPipelineFunc executes the command in given directory with given timeout,
110110
// it pipes stdout and stderr to given io.Writer and passes in an io.Reader as stdin. Between cmd.Start and cmd.Wait the passed in function is run.
111111
func (c *Command) RunInDirTimeoutEnvFullPipelineFunc(env []string, timeout time.Duration, dir string, stdout, stderr io.Writer, stdin io.Reader, fn func(context.Context, context.CancelFunc) error) error {
112-
if timeout == -1 {
113-
timeout = DefaultCommandExecutionTimeout
112+
return c.RunWithContext(&RunContext{
113+
Env: env,
114+
Timeout: timeout,
115+
Dir: dir,
116+
Stdout: stdout,
117+
Stderr: stderr,
118+
Stdin: stdin,
119+
CancelFunc: fn,
120+
})
121+
}
122+
123+
// RunContext represents parameters to run the command
124+
type RunContext struct {
125+
Env []string
126+
Timeout time.Duration
127+
Dir string
128+
Stdout, Stderr io.Writer
129+
Stdin io.Reader
130+
CancelFunc func(context.Context, context.CancelFunc) error
131+
}
132+
133+
// RunWithContext run the command with context
134+
func (c *Command) RunWithContext(rc *RunContext) error {
135+
if rc.Timeout == -1 {
136+
rc.Timeout = DefaultCommandExecutionTimeout
114137
}
115138

116-
if len(dir) == 0 {
139+
if len(rc.Dir) == 0 {
117140
log(c.String())
118141
} else {
119-
log("%s: %v", dir, c)
142+
log("%s: %v", rc.Dir, c)
120143
}
121144

122-
ctx, cancel := context.WithTimeout(c.parentContext, timeout)
145+
ctx, cancel := context.WithTimeout(c.parentContext, rc.Timeout)
123146
defer cancel()
124147

125148
cmd := exec.CommandContext(ctx, c.name, c.args...)
126-
if env == nil {
149+
if rc.Env == nil {
127150
cmd.Env = append(os.Environ(), fmt.Sprintf("LC_ALL=%s", DefaultLocale))
128151
} else {
129-
cmd.Env = env
152+
cmd.Env = rc.Env
130153
cmd.Env = append(cmd.Env, fmt.Sprintf("LC_ALL=%s", DefaultLocale))
131154
}
132155

133156
// TODO: verify if this is still needed in golang 1.15
134157
if goVersionLessThan115 {
135158
cmd.Env = append(cmd.Env, "GODEBUG=asyncpreemptoff=1")
136159
}
137-
cmd.Dir = dir
138-
cmd.Stdout = stdout
139-
cmd.Stderr = stderr
140-
cmd.Stdin = stdin
160+
cmd.Dir = rc.Dir
161+
cmd.Stdout = rc.Stdout
162+
cmd.Stderr = rc.Stderr
163+
cmd.Stdin = rc.Stdin
141164
if err := cmd.Start(); err != nil {
142165
return err
143166
}
144167

145168
desc := c.desc
146169
if desc == "" {
147-
desc = fmt.Sprintf("%s %s %s [repo_path: %s]", GitExecutable, c.name, strings.Join(c.args, " "), dir)
170+
desc = fmt.Sprintf("%s %s %s [repo_path: %s]", GitExecutable, c.name, strings.Join(c.args, " "), rc.Dir)
148171
}
149172
pid := process.GetManager().Add(desc, cancel)
150173
defer process.GetManager().Remove(pid)
151174

152-
if fn != nil {
153-
err := fn(ctx, cancel)
175+
if rc.CancelFunc != nil {
176+
err := rc.CancelFunc(ctx, cancel)
154177
if err != nil {
155178
cancel()
156179
_ = cmd.Wait()

modules/git/git.go

+36
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"time"
1515

1616
"code.gitea.io/gitea/modules/process"
17+
"code.gitea.io/gitea/modules/setting"
1718

1819
"github.com/hashicorp/go-version"
1920
)
@@ -122,10 +123,45 @@ func SetExecutablePath(path string) error {
122123
return nil
123124
}
124125

126+
// VersionInfo returns git version information
127+
func VersionInfo() string {
128+
var format = "Git Version: %s"
129+
var args = []interface{}{gitVersion.Original()}
130+
// Since git wire protocol has been released from git v2.18
131+
if setting.Git.EnableAutoGitWireProtocol && CheckGitVersionAtLeast("2.18") == nil {
132+
format += ", Wire Protocol %s Enabled"
133+
args = append(args, "Version 2") // for focus color
134+
}
135+
136+
return fmt.Sprintf(format, args...)
137+
}
138+
125139
// Init initializes git module
126140
func Init(ctx context.Context) error {
127141
DefaultContext = ctx
128142

143+
DefaultCommandExecutionTimeout = time.Duration(setting.Git.Timeout.Default) * time.Second
144+
145+
if err := SetExecutablePath(setting.Git.Path); err != nil {
146+
return err
147+
}
148+
149+
// force cleanup args
150+
GlobalCommandArgs = []string{}
151+
152+
if CheckGitVersionAtLeast("2.9") == nil {
153+
// Explicitly disable credential helper, otherwise Git credentials might leak
154+
GlobalCommandArgs = append(GlobalCommandArgs, "-c", "credential.helper=")
155+
}
156+
157+
// Since git wire protocol has been released from git v2.18
158+
if setting.Git.EnableAutoGitWireProtocol && CheckGitVersionAtLeast("2.18") == nil {
159+
GlobalCommandArgs = append(GlobalCommandArgs, "-c", "protocol.version=2")
160+
}
161+
162+
CommitsRangeSize = setting.Git.CommitsRangeSize
163+
BranchesRangeSize = setting.Git.BranchesRangeSize
164+
129165
// Save current git version on init to gitVersion otherwise it would require an RWMutex
130166
if err := LoadGitVersion(); err != nil {
131167
return err

modules/git/lfs.go

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2021 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package git
6+
7+
import (
8+
"sync"
9+
10+
logger "code.gitea.io/gitea/modules/log"
11+
"code.gitea.io/gitea/modules/setting"
12+
)
13+
14+
var once sync.Once
15+
16+
// CheckLFSVersion will check lfs version, if not satisfied, then disable it.
17+
func CheckLFSVersion() {
18+
if setting.LFS.StartServer {
19+
//Disable LFS client hooks if installed for the current OS user
20+
//Needs at least git v2.1.2
21+
22+
err := LoadGitVersion()
23+
if err != nil {
24+
logger.Fatal("Error retrieving git version: %v", err)
25+
}
26+
27+
if CheckGitVersionAtLeast("2.1.2") != nil {
28+
setting.LFS.StartServer = false
29+
logger.Error("LFS server support needs at least Git v2.1.2")
30+
} else {
31+
once.Do(func() {
32+
GlobalCommandArgs = append(GlobalCommandArgs, "-c", "filter.lfs.required=",
33+
"-c", "filter.lfs.smudge=", "-c", "filter.lfs.clean=")
34+
})
35+
}
36+
}
37+
}

modules/git/repo.go

+19-2
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@ import (
1010
"container/list"
1111
"context"
1212
"fmt"
13+
"net/url"
1314
"os"
1415
"path"
1516
"strconv"
1617
"strings"
1718
"time"
19+
20+
"code.gitea.io/gitea/modules/proxy"
1821
)
1922

2023
// GPGSettings represents the default GPG settings for this repository
@@ -147,8 +150,22 @@ func CloneWithArgs(ctx context.Context, from, to string, args []string, opts Clo
147150
opts.Timeout = -1
148151
}
149152

150-
_, err = cmd.RunTimeout(opts.Timeout)
151-
return err
153+
var envs []string
154+
u, err := url.Parse(from)
155+
if err == nil && (strings.EqualFold(u.Scheme, "http") || strings.EqualFold(u.Scheme, "https")) {
156+
if proxy.Match(u.Host) {
157+
envs = []string{fmt.Sprintf("https_proxy=%s", proxy.GetProxy())}
158+
}
159+
}
160+
161+
var stderr = new(bytes.Buffer)
162+
err = cmd.RunWithContext(&RunContext{
163+
Timeout: opts.Timeout,
164+
Env: envs,
165+
Stdout: new(bytes.Buffer),
166+
Stderr: stderr,
167+
})
168+
return ConcatenateError(err, stderr.String())
152169
}
153170

154171
// PullRemoteOptions options when pull from remote

0 commit comments

Comments
 (0)