Skip to content

Commit 2ac2a5b

Browse files
mrsdizzielunny
authored andcommitted
Refactor submodule URL parsing (#7100)
Use combination of url.Parse and regex to parse refURL rather than by hand with indexes & attempt to check if refURL is from same instance and adjust output to match. Also now return empty string instead of our original guess at URL if we are unable to parse it. Fixes #1526
1 parent 45f588e commit 2ac2a5b

File tree

2 files changed

+74
-27
lines changed

2 files changed

+74
-27
lines changed

modules/git/submodule.go

Lines changed: 62 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
1+
// Copyright 2019 The Gitea Authors. All rights reserved.
12
// Copyright 2015 The Gogs Authors. All rights reserved.
23
// Use of this source code is governed by a MIT-style
34
// license that can be found in the LICENSE file.
45

56
package git
67

7-
import "strings"
8+
import (
9+
"fmt"
10+
"net"
11+
"net/url"
12+
"regexp"
13+
"strings"
14+
)
15+
16+
var scpSyntax = regexp.MustCompile(`^([a-zA-Z0-9_]+@)?([a-zA-Z0-9._-]+):(.*)$`)
817

918
// SubModule submodule is a reference on git repository
1019
type SubModule struct {
@@ -34,46 +43,73 @@ func getRefURL(refURL, urlPrefix, parentPath string) string {
3443
return ""
3544
}
3645

37-
url := strings.TrimSuffix(refURL, ".git")
38-
39-
// git://xxx/user/repo
40-
if strings.HasPrefix(url, "git://") {
41-
return "http://" + strings.TrimPrefix(url, "git://")
42-
}
46+
refURI := strings.TrimSuffix(refURL, ".git")
4347

44-
// http[s]://xxx/user/repo
45-
if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") {
46-
return url
48+
prefixURL, _ := url.Parse(urlPrefix)
49+
urlPrefixHostname, _, err := net.SplitHostPort(prefixURL.Host)
50+
if err != nil {
51+
urlPrefixHostname = prefixURL.Host
4752
}
4853

4954
// Relative url prefix check (according to git submodule documentation)
50-
if strings.HasPrefix(url, "./") || strings.HasPrefix(url, "../") {
55+
if strings.HasPrefix(refURI, "./") || strings.HasPrefix(refURI, "../") {
5156
// ...construct and return correct submodule url here...
5257
idx := strings.Index(parentPath, "/src/")
5358
if idx == -1 {
54-
return url
59+
return refURI
5560
}
56-
return strings.TrimSuffix(urlPrefix, "/") + parentPath[:idx] + "/" + url
61+
return strings.TrimSuffix(urlPrefix, "/") + parentPath[:idx] + "/" + refURI
5762
}
5863

59-
// sysuser@xxx:user/repo
60-
i := strings.Index(url, "@")
61-
j := strings.LastIndex(url, ":")
64+
if !strings.Contains(refURI, "://") {
65+
// scp style syntax which contains *no* port number after the : (and is not parsed by net/url)
66+
// ex: [email protected]:go-gitea/gitea
67+
match := scpSyntax.FindAllStringSubmatch(refURI, -1)
68+
if len(match) > 0 {
6269

63-
// Only process when i < j because git+ssh://[email protected]/npploader.git
64-
if i > -1 && j > -1 && i < j {
65-
// fix problem with reverse proxy works only with local server
66-
if strings.Contains(urlPrefix, url[i+1:j]) {
67-
return urlPrefix + url[j+1:]
70+
m := match[0]
71+
refHostname := m[2]
72+
path := m[3]
73+
74+
if !strings.HasPrefix(path, "/") {
75+
path = "/" + path
76+
}
77+
78+
if urlPrefixHostname == refHostname {
79+
return prefixURL.Scheme + "://" + urlPrefixHostname + path
80+
}
81+
return "http://" + refHostname + path
6882
}
69-
if strings.HasPrefix(url, "ssh://") || strings.HasPrefix(url, "git+ssh://") {
70-
k := strings.Index(url[j+1:], "/")
71-
return "http://" + url[i+1:j] + "/" + url[j+1:][k+1:]
83+
}
84+
85+
ref, err := url.Parse(refURI)
86+
if err != nil {
87+
return ""
88+
}
89+
90+
refHostname, _, err := net.SplitHostPort(ref.Host)
91+
if err != nil {
92+
refHostname = ref.Host
93+
}
94+
95+
supportedSchemes := []string{"http", "https", "git", "ssh", "git+ssh"}
96+
97+
for _, scheme := range supportedSchemes {
98+
if ref.Scheme == scheme {
99+
if urlPrefixHostname == refHostname {
100+
return prefixURL.Scheme + "://" + prefixURL.Host + ref.Path
101+
} else if ref.Scheme == "http" || ref.Scheme == "https" {
102+
if len(ref.User.Username()) > 0 {
103+
return ref.Scheme + "://" + fmt.Sprintf("%v", ref.User) + "@" + ref.Host + ref.Path
104+
}
105+
return ref.Scheme + "://" + ref.Host + ref.Path
106+
} else {
107+
return "http://" + refHostname + ref.Path
108+
}
72109
}
73-
return "http://" + url[i+1:j] + "/" + url[j+1:]
74110
}
75111

76-
return url
112+
return ""
77113
}
78114

79115
// RefURL guesses and returns reference URL.

modules/git/submodule_test.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,19 @@ func TestGetRefURL(t *testing.T) {
1919
}{
2020
{"git://github.com/user1/repo1", "/", "/", "http://github.com/user1/repo1"},
2121
{"https://localhost/user1/repo1.git", "/", "/", "https://localhost/user1/repo1"},
22-
{"[email protected]/user1/repo1.git", "/", "/", "[email protected]/user1/repo1"},
22+
{"http://localhost/user1/repo1.git", "/", "/", "http://localhost/user1/repo1"},
23+
{"[email protected]:user1/repo1.git", "/", "/", "http://github.com/user1/repo1"},
2324
{"ssh://[email protected]:2222/zefie/lge_g6_kernel_scripts.git", "/", "/", "http://git.zefie.net/zefie/lge_g6_kernel_scripts"},
25+
{"[email protected]:2222/zefie/lge_g6_kernel_scripts.git", "/", "/", "http://git.zefie.net/2222/zefie/lge_g6_kernel_scripts"},
26+
{"[email protected]:go-gitea/gitea", "https://try.gitea.io/go-gitea/gitea", "/", "https://try.gitea.io/go-gitea/gitea"},
27+
{"ssh://[email protected]:9999/go-gitea/gitea", "https://try.gitea.io/go-gitea/gitea", "/", "https://try.gitea.io/go-gitea/gitea"},
28+
{"git://[email protected]:9999/go-gitea/gitea", "https://try.gitea.io/go-gitea/log", "/", "https://try.gitea.io/go-gitea/gitea"},
29+
{"ssh://[email protected]:9999/go-gitea/gitea", "https://127.0.0.1:3000/go-gitea/log", "/", "https://127.0.0.1:3000/go-gitea/gitea"},
30+
{"https://gitea.com:3000/user1/repo1.git", "https://127.0.0.1:3000/go-gitea/gitea", "/", "https://gitea.com:3000/user1/repo1"},
31+
{"https://username:[email protected]/username/repository.git", "/", "/", "https://username:[email protected]/username/repository"},
32+
{"somethingbad", "https://127.0.0.1:3000/go-gitea/gitea", "/", ""},
33+
{"git@localhost:user/repo", "https://localhost/user/repo2", "/", "https://localhost/user/repo"},
34+
{"../path/to/repo.git/", "https://localhost/user/repo2/src/branch/master/test", "/", "../path/to/repo.git/"},
2435
}
2536

2637
for _, kase := range kases {

0 commit comments

Comments
 (0)