@@ -13,6 +13,9 @@ import ( | |||
"strings" | |||
"time" | |||
"code.gitea.io/gitea/modules/setting" | |||
"golang.org/x/net/proxy" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/migrations/base" | |||
"code.gitea.io/gitea/modules/structs" | |||
@@ -98,13 +101,41 @@ func NewGithubDownloaderV3(userName, password, repoOwner, repoName string) *Gith | |||
) | |||
client = oauth2.NewClient(downloader.ctx, ts) | |||
} else { | |||
client = &http.Client{ | |||
Transport: &http.Transport{ | |||
Proxy: func(req *http.Request) (*url.URL, error) { | |||
req.SetBasicAuth(userName, password) | |||
return nil, nil | |||
if setting.Migrations.Proxy != "" { | |||
contextDialer, err := getProxyDialContext() | |||
if err != nil { | |||
log.Warn("Failed to use proxy for Github.", err) | |||
client = &http.Client{ | |||
Transport: &http.Transport{ | |||
Proxy: func(req *http.Request) (*url.URL, error) { | |||
req.SetBasicAuth(userName, password) | |||
return nil, nil | |||
}, | |||
}, | |||
} | |||
} else { | |||
client = &http.Client{ | |||
Transport: &http.Transport{ | |||
Proxy: func(req *http.Request) (*url.URL, error) { | |||
req.SetBasicAuth(userName, password) | |||
return nil, nil | |||
}, | |||
DialContext: contextDialer.DialContext, | |||
}, | |||
} | |||
} | |||
} else { | |||
client = &http.Client{ | |||
Transport: &http.Transport{ | |||
Proxy: func(req *http.Request) (*url.URL, error) { | |||
req.SetBasicAuth(userName, password) | |||
return nil, nil | |||
}, | |||
}, | |||
}, | |||
} | |||
} | |||
} | |||
} | |||
@@ -112,6 +143,25 @@ func NewGithubDownloaderV3(userName, password, repoOwner, repoName string) *Gith | |||
return &downloader | |||
} | |||
func getProxyDialContext() (proxy.ContextDialer, error) { | |||
authInfo := &proxy.Auth{ | |||
setting.Migrations.Username, | |||
setting.Migrations.Password, | |||
} | |||
dialSocksProxy, err := proxy.SOCKS5("tcp", setting.Migrations.Proxy, authInfo, proxy.Direct) | |||
if err != nil { | |||
return nil, err | |||
} | |||
if contextDialer, ok := dialSocksProxy.(proxy.ContextDialer); ok { | |||
return contextDialer, nil | |||
} else { | |||
return nil, fmt.Errorf("It is not a valiad dialer.") | |||
} | |||
} | |||
// SetContext set context | |||
func (g *GithubDownloaderV3) SetContext(ctx context.Context) { | |||
g.ctx = ctx | |||
@@ -6,6 +6,7 @@ package repository | |||
import ( | |||
"fmt" | |||
"net/url" | |||
"os" | |||
"path" | |||
"strings" | |||
@@ -54,29 +55,34 @@ func MigrateRepositoryGitData(doer, u *models.User, repo *models.Repository, opt | |||
repo.NumWatches = 1 | |||
} | |||
migrateTimeout := time.Duration(setting.Git.Timeout.Migrate) * time.Second | |||
migrateTimeout := getMigrateTimeout(opts.CloneAddr) | |||
var err error | |||
if err = os.RemoveAll(repoPath); err != nil { | |||
return repo, fmt.Errorf("Failed to remove %s: %v", repoPath, err) | |||
} | |||
log.Info("clone begin:" + opts.CloneAddr) | |||
if err = git.Clone(opts.CloneAddr, repoPath, git.CloneRepoOptions{ | |||
Mirror: true, | |||
Quiet: true, | |||
Timeout: migrateTimeout, | |||
}); err != nil { | |||
log.Warn("clone err") | |||
return repo, fmt.Errorf("Clone: %v", err) | |||
} | |||
log.Info("clone end:" + opts.CloneAddr) | |||
if opts.Wiki { | |||
log.Info("test wiki path begin") | |||
wikiPath := models.WikiPath(u.Name, opts.RepoName) | |||
wikiRemotePath := wikiRemoteURL(opts.CloneAddr) | |||
log.Info("test wiki path end") | |||
if len(wikiRemotePath) > 0 { | |||
if err := os.RemoveAll(wikiPath); err != nil { | |||
return repo, fmt.Errorf("Failed to remove %s: %v", wikiPath, err) | |||
} | |||
log.Info("wiki clone begin") | |||
if err = git.Clone(wikiRemotePath, wikiPath, git.CloneRepoOptions{ | |||
Mirror: true, | |||
Quiet: true, | |||
@@ -88,6 +94,7 @@ func MigrateRepositoryGitData(doer, u *models.User, repo *models.Repository, opt | |||
return repo, fmt.Errorf("Failed to remove %s: %v", wikiPath, err) | |||
} | |||
} | |||
log.Info("wiki clone end") | |||
} | |||
} | |||
@@ -137,9 +144,20 @@ func MigrateRepositoryGitData(doer, u *models.User, repo *models.Repository, opt | |||
repo, err = CleanUpMigrateInfo(repo) | |||
} | |||
log.Info("clone all end:" + opts.CloneAddr) | |||
return repo, err | |||
} | |||
func getMigrateTimeout(urlClone string) time.Duration { | |||
u, err := url.Parse(urlClone) | |||
if err == nil && strings.EqualFold(u.Host, "github.com") { | |||
return time.Duration(setting.Git.Timeout.GitHubMigrate) * time.Second | |||
} | |||
return time.Duration(setting.Git.Timeout.Migrate) * time.Second | |||
} | |||
// cleanUpMigrateGitConfig removes mirror info which prevents "push --all". | |||
// This also removes possible user credentials. | |||
func cleanUpMigrateGitConfig(configPath string) error { | |||
@@ -27,12 +27,13 @@ var ( | |||
EnableAutoGitWireProtocol bool | |||
PullRequestPushMessage bool | |||
Timeout struct { | |||
Default int | |||
Migrate int | |||
Mirror int | |||
Clone int | |||
Pull int | |||
GC int `ini:"GC"` | |||
Default int | |||
Migrate int | |||
GitHubMigrate int | |||
Mirror int | |||
Clone int | |||
Pull int | |||
GC int `ini:"GC"` | |||
} `ini:"git.timeout"` | |||
}{ | |||
DisableDiffHighlight: false, | |||
@@ -45,19 +46,21 @@ var ( | |||
EnableAutoGitWireProtocol: true, | |||
PullRequestPushMessage: true, | |||
Timeout: struct { | |||
Default int | |||
Migrate int | |||
Mirror int | |||
Clone int | |||
Pull int | |||
GC int `ini:"GC"` | |||
Default int | |||
Migrate int | |||
GitHubMigrate int | |||
Mirror int | |||
Clone int | |||
Pull int | |||
GC int `ini:"GC"` | |||
}{ | |||
Default: int(git.DefaultCommandExecutionTimeout / time.Second), | |||
Migrate: 600, | |||
Mirror: 300, | |||
Clone: 300, | |||
Pull: 300, | |||
GC: 60, | |||
Default: int(git.DefaultCommandExecutionTimeout / time.Second), | |||
Migrate: 900, | |||
GitHubMigrate: 1800, | |||
Mirror: 1200, | |||
Clone: 300, | |||
Pull: 300, | |||
GC: 60, | |||
}, | |||
} | |||
) | |||
@@ -9,6 +9,9 @@ var ( | |||
Migrations = struct { | |||
MaxAttempts int | |||
RetryBackoff int | |||
Proxy string | |||
Username string | |||
Password string | |||
}{ | |||
MaxAttempts: 3, | |||
RetryBackoff: 3, | |||
@@ -19,4 +22,7 @@ func newMigrationsService() { | |||
sec := Cfg.Section("migrations") | |||
Migrations.MaxAttempts = sec.Key("MAX_ATTEMPTS").MustInt(Migrations.MaxAttempts) | |||
Migrations.RetryBackoff = sec.Key("RETRY_BACKOFF").MustInt(Migrations.RetryBackoff) | |||
Migrations.Proxy = sec.Key("Proxy").MustString("") | |||
Migrations.Username = sec.Key("Username").MustString("") | |||
Migrations.Password = sec.Key("Password").MustString("") | |||
} |