|
| 1 | +// Copyright 2019 The Gitea Authors. All rights reserved. |
1 | 2 | // Copyright 2015 The Gogs Authors. All rights reserved.
|
2 | 3 | // Use of this source code is governed by a MIT-style
|
3 | 4 | // license that can be found in the LICENSE file.
|
4 | 5 |
|
5 | 6 | package git
|
6 | 7 |
|
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._-]+):(.*)$`) |
8 | 17 |
|
9 | 18 | // SubModule submodule is a reference on git repository
|
10 | 19 | type SubModule struct {
|
@@ -34,46 +43,73 @@ func getRefURL(refURL, urlPrefix, parentPath string) string {
|
34 | 43 | return ""
|
35 | 44 | }
|
36 | 45 |
|
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") |
43 | 47 |
|
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 |
47 | 52 | }
|
48 | 53 |
|
49 | 54 | // 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, "../") { |
51 | 56 | // ...construct and return correct submodule url here...
|
52 | 57 | idx := strings.Index(parentPath, "/src/")
|
53 | 58 | if idx == -1 {
|
54 |
| - return url |
| 59 | + return refURI |
55 | 60 | }
|
56 |
| - return strings.TrimSuffix(urlPrefix, "/") + parentPath[:idx] + "/" + url |
| 61 | + return strings.TrimSuffix(urlPrefix, "/") + parentPath[:idx] + "/" + refURI |
57 | 62 | }
|
58 | 63 |
|
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 { |
62 | 69 |
|
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 |
68 | 82 | }
|
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 | + } |
72 | 109 | }
|
73 |
| - return "http://" + url[i+1:j] + "/" + url[j+1:] |
74 | 110 | }
|
75 | 111 |
|
76 |
| - return url |
| 112 | + return "" |
77 | 113 | }
|
78 | 114 |
|
79 | 115 | // RefURL guesses and returns reference URL.
|
|
0 commit comments