fix #12192 Support SSH for go get --------- Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: Giteabot <teabot@gitea.io> Co-authored-by: mfk <mfk@hengwei.com.cn> Co-authored-by: silverwind <me@silverwind.io>tags/v1.20.0-rc0
@@ -940,6 +940,9 @@ ROUTER = console | |||
;; Force ssh:// clone url instead of scp-style uri when default SSH port is used | |||
;USE_COMPAT_SSH_URI = false | |||
;; | |||
;; Value for the "go get" request returns the repository url as https or ssh, default is https | |||
;GO_GET_CLONE_URL_PROTOCOL = https | |||
;; | |||
;; Close issues as long as a commit on any branch marks it as fixed | |||
;; Comma separated list of globally disabled repo units. Allowed values: repo.issues, repo.ext_issues, repo.pulls, repo.wiki, repo.ext_wiki, repo.projects, repo.packages, repo.actions. | |||
;DISABLED_REPO_UNITS = |
@@ -95,6 +95,8 @@ In addition there is _`StaticRootPath`_ which can be set as a built-in at build | |||
HTTP protocol. | |||
- `USE_COMPAT_SSH_URI`: **false**: Force ssh:// clone url instead of scp-style uri when | |||
default SSH port is used. | |||
- `GO_GET_CLONE_URL_PROTOCOL`: **https**: Value for the "go get" request returns the repository url as https or ssh | |||
default is https. | |||
- `ACCESS_CONTROL_ALLOW_ORIGIN`: **\<empty\>**: Value for Access-Control-Allow-Origin header, | |||
default is not to present. **WARNING**: This maybe harmful to you website if you do not | |||
give it a right value. |
@@ -547,16 +547,9 @@ func ComposeHTTPSCloneURL(owner, repo string) string { | |||
return fmt.Sprintf("%s%s/%s.git", setting.AppURL, url.PathEscape(owner), url.PathEscape(repo)) | |||
} | |||
func (repo *Repository) cloneLink(isWiki bool) *CloneLink { | |||
repoName := repo.Name | |||
if isWiki { | |||
repoName += ".wiki" | |||
} | |||
func ComposeSSHCloneURL(ownerName, repoName string) string { | |||
sshUser := setting.SSH.User | |||
cl := new(CloneLink) | |||
// if we have a ipv6 literal we need to put brackets around it | |||
// for the git cloning to work. | |||
sshDomain := setting.SSH.Domain | |||
@@ -566,12 +559,25 @@ func (repo *Repository) cloneLink(isWiki bool) *CloneLink { | |||
} | |||
if setting.SSH.Port != 22 { | |||
cl.SSH = fmt.Sprintf("ssh://%s@%s/%s/%s.git", sshUser, net.JoinHostPort(setting.SSH.Domain, strconv.Itoa(setting.SSH.Port)), url.PathEscape(repo.OwnerName), url.PathEscape(repoName)) | |||
} else if setting.Repository.UseCompatSSHURI { | |||
cl.SSH = fmt.Sprintf("ssh://%s@%s/%s/%s.git", sshUser, sshDomain, url.PathEscape(repo.OwnerName), url.PathEscape(repoName)) | |||
} else { | |||
cl.SSH = fmt.Sprintf("%s@%s:%s/%s.git", sshUser, sshDomain, url.PathEscape(repo.OwnerName), url.PathEscape(repoName)) | |||
return fmt.Sprintf("ssh://%s@%s/%s/%s.git", sshUser, | |||
net.JoinHostPort(setting.SSH.Domain, strconv.Itoa(setting.SSH.Port)), | |||
url.PathEscape(ownerName), | |||
url.PathEscape(repoName)) | |||
} | |||
if setting.Repository.UseCompatSSHURI { | |||
return fmt.Sprintf("ssh://%s@%s/%s/%s.git", sshUser, sshDomain, url.PathEscape(ownerName), url.PathEscape(repoName)) | |||
} | |||
return fmt.Sprintf("%s@%s:%s/%s.git", sshUser, sshDomain, url.PathEscape(ownerName), url.PathEscape(repoName)) | |||
} | |||
func (repo *Repository) cloneLink(isWiki bool) *CloneLink { | |||
repoName := repo.Name | |||
if isWiki { | |||
repoName += ".wiki" | |||
} | |||
cl := new(CloneLink) | |||
cl.SSH = ComposeSSHCloneURL(repo.OwnerName, repoName) | |||
cl.HTTPS = ComposeHTTPSCloneURL(repo.OwnerName, repoName) | |||
return cl | |||
} |
@@ -319,7 +319,14 @@ func EarlyResponseForGoGetMeta(ctx *Context) { | |||
ctx.PlainText(http.StatusBadRequest, "invalid repository path") | |||
return | |||
} | |||
goImportContent := fmt.Sprintf("%s git %s", ComposeGoGetImport(username, reponame), repo_model.ComposeHTTPSCloneURL(username, reponame)) | |||
var cloneURL string | |||
if setting.Repository.GoGetCloneURLProtocol == "ssh" { | |||
cloneURL = repo_model.ComposeSSHCloneURL(username, reponame) | |||
} else { | |||
cloneURL = repo_model.ComposeHTTPSCloneURL(username, reponame) | |||
} | |||
goImportContent := fmt.Sprintf("%s git %s", ComposeGoGetImport(username, reponame), cloneURL) | |||
htmlMeta := fmt.Sprintf(`<meta name="go-import" content="%s">`, html.EscapeString(goImportContent)) | |||
ctx.PlainText(http.StatusOK, htmlMeta) | |||
} |
@@ -36,6 +36,7 @@ var ( | |||
DisableHTTPGit bool | |||
AccessControlAllowOrigin string | |||
UseCompatSSHURI bool | |||
GoGetCloneURLProtocol string | |||
DefaultCloseIssuesViaCommitsInAnyBranch bool | |||
EnablePushCreateUser bool | |||
EnablePushCreateOrg bool | |||
@@ -273,6 +274,7 @@ func loadRepositoryFrom(rootCfg ConfigProvider) { | |||
sec := rootCfg.Section("repository") | |||
Repository.DisableHTTPGit = sec.Key("DISABLE_HTTP_GIT").MustBool() | |||
Repository.UseCompatSSHURI = sec.Key("USE_COMPAT_SSH_URI").MustBool() | |||
Repository.GoGetCloneURLProtocol = sec.Key("GO_GET_CLONE_URL_PROTOCOL").MustString("https") | |||
Repository.MaxCreationLimit = sec.Key("MAX_CREATION_LIMIT").MustInt(-1) | |||
Repository.DefaultBranch = sec.Key("DEFAULT_BRANCH").MustString(Repository.DefaultBranch) | |||
RepoRootPath = sec.Key("ROOT").MustString(path.Join(AppDataPath, "gitea-repositories")) |
@@ -66,7 +66,14 @@ func goGet(ctx *context.Context) { | |||
} | |||
goGetImport := context.ComposeGoGetImport(ownerName, trimmedRepoName) | |||
goImportContent := fmt.Sprintf("%s git %s", goGetImport, repo_model.ComposeHTTPSCloneURL(ownerName, repoName) /*CloneLink*/) | |||
var cloneURL string | |||
if setting.Repository.GoGetCloneURLProtocol == "ssh" { | |||
cloneURL = repo_model.ComposeSSHCloneURL(ownerName, repoName) | |||
} else { | |||
cloneURL = repo_model.ComposeHTTPSCloneURL(ownerName, repoName) | |||
} | |||
goImportContent := fmt.Sprintf("%s git %s", goGetImport, cloneURL /*CloneLink*/) | |||
goSourceContent := fmt.Sprintf("%s _ %s %s", goGetImport, prefix+"{/dir}" /*GoDocDirectory*/, prefix+"{/dir}/{file}#L{line}" /*GoDocFile*/) | |||
goGetCli := fmt.Sprintf("go get %s%s", insecure, goGetImport) | |||
@@ -33,3 +33,29 @@ func TestGoGet(t *testing.T) { | |||
assert.Equal(t, expected, resp.Body.String()) | |||
} | |||
func TestGoGetForSSH(t *testing.T) { | |||
defer tests.PrepareTestEnv(t)() | |||
old := setting.Repository.GoGetCloneURLProtocol | |||
defer func() { | |||
setting.Repository.GoGetCloneURLProtocol = old | |||
}() | |||
setting.Repository.GoGetCloneURLProtocol = "ssh" | |||
req := NewRequest(t, "GET", "/blah/glah/plah?go-get=1") | |||
resp := MakeRequest(t, req, http.StatusOK) | |||
expected := fmt.Sprintf(`<!doctype html> | |||
<html> | |||
<head> | |||
<meta name="go-import" content="%[1]s:%[2]s/blah/glah git ssh://git@%[4]s:%[5]d/blah/glah.git"> | |||
<meta name="go-source" content="%[1]s:%[2]s/blah/glah _ %[3]sblah/glah/src/branch/master{/dir} %[3]sblah/glah/src/branch/master{/dir}/{file}#L{line}"> | |||
</head> | |||
<body> | |||
go get --insecure %[1]s:%[2]s/blah/glah | |||
</body> | |||
</html>`, setting.Domain, setting.HTTPPort, setting.AppURL, setting.SSH.Domain, setting.SSH.Port) | |||
assert.Equal(t, expected, resp.Body.String()) | |||
} |