Skip to content

Commit ecb943b

Browse files
committed
Provide mechanism for configuring submodule aliases
Sometimes Gitea users would like submodules when displayed on the website to have a different alias than what is normally inferred by gitea. This PR provides a mechanism to configure this. Fix #15178 Signed-off-by: Andrew Thornton <[email protected]>
1 parent 6b836ac commit ecb943b

File tree

6 files changed

+120
-23
lines changed

6 files changed

+120
-23
lines changed

custom/conf/app.example.ini

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,6 +1145,13 @@ CLONE = 300
11451145
PULL = 300
11461146
GC = 60
11471147

1148+
; Submodule aliase
1149+
; [git.submodule]
1150+
; MAP_NAME_1 = [email protected]
1151+
; MAP_VALUE_1 = https://example.com
1152+
; MAP_NAME_2 = [email protected]/go-gitea/gitea
1153+
; MAP_VALUE_2 = https://gitea.com/gitea/gitea
1154+
11481155
[mirror]
11491156
; Default interval as a duration between each check
11501157
DEFAULT_INTERVAL = 8h

docs/content/doc/advanced/config-cheat-sheet.en-us.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,13 +782,20 @@ NB: You must have `DISABLE_ROUTER_LOG` set to `false` for this option to take ef
782782
- `VERBOSE_PUSH_DELAY`: **5s**: Only print verbose information if push takes longer than this delay.
783783

784784
## Git - Timeout settings (`git.timeout`)
785+
785786
- `DEFAUlT`: **360**: Git operations default timeout seconds.
786787
- `MIGRATE`: **600**: Migrate external repositories timeout seconds.
787788
- `MIRROR`: **300**: Mirror external repositories timeout seconds.
788789
- `CLONE`: **300**: Git clone from internal repositories timeout seconds.
789790
- `PULL`: **300**: Git pull from internal repositories timeout seconds.
790791
- `GC`: **60**: Git repository GC timeout seconds.
791792

793+
## Git - Submodule alias settings (`git.submodule`)
794+
795+
- List of `MAP_NAME_` and `MAP_VALUE_` pairs that map submodule urls or partial urls to web paths. For example:
796+
- `MAP_NAME_1 = [email protected]` & `MAP_VALUE_1 = https://external` would convert any submodules referring to `[email protected]` to `https://external`
797+
- `MAP_NAME_A = [email protected]:owner/repo` & `MAP_VALUE_A = https://external/externalowner/externalrepo`
798+
792799
## Metrics (`metrics`)
793800

794801
- `ENABLED`: **false**: Enables /metrics endpoint for prometheus.

modules/git/git.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ var (
3939

4040
// will be checked on Init
4141
goVersionLessThan115 = true
42+
43+
SubModuleMap = map[string]string{}
4244
)
4345

4446
func log(format string, args ...interface{}) {

modules/git/submodule.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,16 @@ func getRefURL(refURL, urlPrefix, repoFullName, sshDomain string) string {
4444
return ""
4545
}
4646

47+
if alias, ok := SubModuleMap[refURL]; ok {
48+
return alias
49+
}
50+
4751
refURI := strings.TrimSuffix(refURL, ".git")
4852

53+
if alias, ok := SubModuleMap[refURI]; ok {
54+
return alias
55+
}
56+
4957
prefixURL, _ := url.Parse(urlPrefix)
5058
urlPrefixHostname, _, err := net.SplitHostPort(prefixURL.Host)
5159
if err != nil {
@@ -76,6 +84,10 @@ func getRefURL(refURL, urlPrefix, repoFullName, sshDomain string) string {
7684
pth = "/" + pth
7785
}
7886

87+
if alias, ok := SubModuleMap[m[1]+refHostname]; ok {
88+
return alias + pth
89+
}
90+
7991
if urlPrefixHostname == refHostname || refHostname == sshDomain {
8092
return urlPrefix + path.Clean(path.Join("/", pth))
8193
}
@@ -95,6 +107,33 @@ func getRefURL(refURL, urlPrefix, repoFullName, sshDomain string) string {
95107

96108
supportedSchemes := []string{"http", "https", "git", "ssh", "git+ssh"}
97109

110+
if len(SubModuleMap) > 0 && ref.Scheme != "" {
111+
if ref.Scheme == "ssh" {
112+
if len(ref.User.Username()) > 0 {
113+
if alias, ok := SubModuleMap[fmt.Sprintf("%v@%s:%s", ref.User, ref.Host, ref.Path[1:])]; ok {
114+
return alias
115+
}
116+
if alias, ok := SubModuleMap[fmt.Sprintf("%v@%s", ref.User, ref.Host)]; ok {
117+
return alias + ref.Path
118+
}
119+
} else if alias, ok := SubModuleMap[ref.Host+":"+ref.Path[1:]]; ok {
120+
return alias
121+
} else if alias, ok := SubModuleMap[ref.Host]; ok {
122+
return alias + ref.Path
123+
}
124+
}
125+
left := refURI
126+
right := ""
127+
for idx := strings.LastIndex(left, "/"); idx > len(ref.Scheme)+3; {
128+
right = left[idx:] + right
129+
left = left[:idx]
130+
if alias, ok := SubModuleMap[left]; ok {
131+
return alias + right
132+
}
133+
idx = strings.LastIndex(left, "/")
134+
}
135+
}
136+
98137
for _, scheme := range supportedSchemes {
99138
if ref.Scheme == scheme {
100139
if ref.Scheme == "http" || ref.Scheme == "https" {

modules/git/submodule_test.go

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,32 +12,55 @@ import (
1212

1313
func TestGetRefURL(t *testing.T) {
1414
var kases = []struct {
15-
refURL string
16-
prefixURL string
17-
parentPath string
18-
SSHDomain string
19-
expect string
15+
refURL string
16+
prefixURL string
17+
parentPath string
18+
SSHDomain string
19+
expect string
20+
subModuleMap map[string]string
2021
}{
21-
{"git://github.com/user1/repo1", "/", "user1/repo2", "", "http://github.com/user1/repo1"},
22-
{"https://localhost/user1/repo1.git", "/", "user1/repo2", "", "https://localhost/user1/repo1"},
23-
{"http://localhost/user1/repo1.git", "/", "owner/reponame", "", "http://localhost/user1/repo1"},
24-
{"[email protected]:user1/repo1.git", "/", "owner/reponame", "", "http://github.com/user1/repo1"},
25-
{"ssh://[email protected]:2222/zefie/lge_g6_kernel_scripts.git", "/", "zefie/lge_g6_kernel", "", "http://git.zefie.net/zefie/lge_g6_kernel_scripts"},
26-
{"[email protected]:2222/zefie/lge_g6_kernel_scripts.git", "/", "zefie/lge_g6_kernel", "", "http://git.zefie.net/2222/zefie/lge_g6_kernel_scripts"},
27-
{"[email protected]:go-gitea/gitea", "https://try.gitea.io/", "go-gitea/sdk", "", "https://try.gitea.io/go-gitea/gitea"},
28-
{"ssh://[email protected]:9999/go-gitea/gitea", "https://try.gitea.io/", "go-gitea/sdk", "", "https://try.gitea.io/go-gitea/gitea"},
29-
{"git://[email protected]:9999/go-gitea/gitea", "https://try.gitea.io/", "go-gitea/sdk", "", "https://try.gitea.io/go-gitea/gitea"},
30-
{"ssh://[email protected]:9999/go-gitea/gitea", "https://127.0.0.1:3000/", "go-gitea/sdk", "", "https://127.0.0.1:3000/go-gitea/gitea"},
31-
{"https://gitea.com:3000/user1/repo1.git", "https://127.0.0.1:3000/", "user/repo2", "", "https://gitea.com:3000/user1/repo1"},
32-
{"https://example.gitea.com/gitea/user1/repo1.git", "https://example.gitea.com/gitea/", "", "user/repo2", "https://example.gitea.com/gitea/user1/repo1"},
33-
{"https://username:[email protected]/username/repository.git", "/", "username/repository2", "", "https://username:[email protected]/username/repository"},
34-
{"somethingbad", "https://127.0.0.1:3000/go-gitea/gitea", "/", "", ""},
35-
{"git@localhost:user/repo", "https://localhost/", "user2/repo1", "", "https://localhost/user/repo"},
36-
{"../path/to/repo.git/", "https://localhost/", "user/repo2", "", "https://localhost/user/path/to/repo.git"},
37-
{"ssh://[email protected]:2222/go-gitea/gitea", "https://try.gitea.io/", "go-gitea/sdk", "ssh.gitea.io", "https://try.gitea.io/go-gitea/gitea"},
22+
{"git://github.com/user1/repo1", "/", "user1/repo2", "", "http://github.com/user1/repo1", map[string]string{}},
23+
{"https://localhost/user1/repo1.git", "/", "user1/repo2", "", "https://localhost/user1/repo1", map[string]string{}},
24+
{"http://localhost/user1/repo1.git", "/", "owner/reponame", "", "http://localhost/user1/repo1", map[string]string{}},
25+
{"[email protected]:user1/repo1.git", "/", "owner/reponame", "", "http://github.com/user1/repo1", map[string]string{}},
26+
{"ssh://[email protected]:2222/zefie/lge_g6_kernel_scripts.git", "/", "zefie/lge_g6_kernel", "", "http://git.zefie.net/zefie/lge_g6_kernel_scripts", map[string]string{}},
27+
{"[email protected]:2222/zefie/lge_g6_kernel_scripts.git", "/", "zefie/lge_g6_kernel", "", "http://git.zefie.net/2222/zefie/lge_g6_kernel_scripts", map[string]string{}},
28+
{"[email protected]:go-gitea/gitea", "https://try.gitea.io/", "go-gitea/sdk", "", "https://try.gitea.io/go-gitea/gitea", map[string]string{}},
29+
{"ssh://[email protected]:9999/go-gitea/gitea", "https://try.gitea.io/", "go-gitea/sdk", "", "https://try.gitea.io/go-gitea/gitea", map[string]string{}},
30+
{"git://[email protected]:9999/go-gitea/gitea", "https://try.gitea.io/", "go-gitea/sdk", "", "https://try.gitea.io/go-gitea/gitea", map[string]string{}},
31+
{"ssh://[email protected]:9999/go-gitea/gitea", "https://127.0.0.1:3000/", "go-gitea/sdk", "", "https://127.0.0.1:3000/go-gitea/gitea", map[string]string{}},
32+
{"https://gitea.com:3000/user1/repo1.git", "https://127.0.0.1:3000/", "user/repo2", "", "https://gitea.com:3000/user1/repo1", map[string]string{}},
33+
{"https://example.gitea.com/gitea/user1/repo1.git", "https://example.gitea.com/gitea/", "", "user/repo2", "https://example.gitea.com/gitea/user1/repo1", map[string]string{}},
34+
{"https://username:[email protected]/username/repository.git", "/", "username/repository2", "", "https://username:[email protected]/username/repository", map[string]string{}},
35+
{"somethingbad", "https://127.0.0.1:3000/go-gitea/gitea", "/", "", "", map[string]string{}},
36+
{"git@localhost:user/repo", "https://localhost/", "user2/repo1", "", "https://localhost/user/repo", map[string]string{}},
37+
{"../path/to/repo.git/", "https://localhost/", "user/repo2", "", "https://localhost/user/path/to/repo.git", map[string]string{}},
38+
{"ssh://[email protected]:2222/go-gitea/gitea", "https://try.gitea.io/", "go-gitea/sdk", "ssh.gitea.io", "https://try.gitea.io/go-gitea/gitea", map[string]string{}},
39+
{"ssh://[email protected]:2222/go-gitea/gitea", "https://try.gitea.io/", "go-gitea/sdk", "try.gitea.io", "https://try.gitea.io/go-gitea/gitea", map[string]string{
40+
"ssh://[email protected]:2222": "https://try.gitea.io",
41+
}},
42+
{"[email protected]:go-gitea/gitea", "https://try.gitea.io/", "go-gitea/sdk", "try.gitea.io", "https://try.gitea.io/go-gitea/gitea", map[string]string{
43+
"[email protected]": "https://try.gitea.io",
44+
"ssh://[email protected]:2222": "Wrong",
45+
}},
46+
{"ssh://[email protected]/go-gitea/gitea", "https://try.gitea.io/", "go-gitea/sdk", "try.gitea.io", "https://try.gitea.io/go-gitea/gitea", map[string]string{
47+
"ssh://[email protected]": "https://try.gitea.io",
48+
"ssh://[email protected]:2222": "Wrong",
49+
}},
50+
{"ssh://[email protected]/go-gitea/gitea", "https://try.gitea.io/", "go-gitea/sdk", "try.gitea.io", "https://try.gitea.io/go-gitea/gitea", map[string]string{
51+
"[email protected]": "https://try.gitea.io",
52+
}},
53+
{"ssh://[email protected]/go-gitea/gitea", "https://try.gitea.io/", "go-gitea/sdk", "try.gitea.io", "https://try.gitea.io/go-gitea/gitea", map[string]string{
54+
"[email protected]": "https://try.gitea.io",
55+
}},
56+
{"ssh://[email protected]/go-gitea/gitea", "https://try.gitea.io/", "go-gitea/sdk", "try.gitea.io", "https://try.gitea.io/go-gitea/gitea", map[string]string{
57+
"[email protected]:go-gitea/gitea": "https://try.gitea.io/go-gitea/gitea",
58+
}},
3859
}
39-
60+
orig := SubModuleMap
4061
for _, kase := range kases {
62+
SubModuleMap = kase.subModuleMap
4163
assert.EqualValues(t, kase.expect, getRefURL(kase.refURL, kase.prefixURL, kase.parentPath, kase.SSHDomain))
4264
}
65+
SubModuleMap = orig
4366
}

modules/setting/git.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package setting
66

77
import (
8+
"strings"
89
"time"
910

1011
"code.gitea.io/gitea/modules/git"
@@ -99,4 +100,22 @@ func newGit() {
99100
git.BranchesRangeSize = Git.BranchesRangeSize
100101

101102
log.Info(format, args...)
103+
104+
submoduleSection := Cfg.Section("git.submodule")
105+
for key, nameValue := range submoduleSection.KeysHash() {
106+
if !strings.HasPrefix(key, "MAP_NAME_") {
107+
continue
108+
}
109+
if nameValue == "" {
110+
continue
111+
}
112+
if !submoduleSection.HasKey("MAP_VALUE_" + key[9:]) {
113+
log.Error("Missing value for submodule map: %s", key)
114+
continue
115+
}
116+
valueValue := submoduleSection.Key("MAP_VALUE_" + key[9:]).MustString("")
117+
if valueValue != "" {
118+
git.SubModuleMap[nameValue] = valueValue
119+
}
120+
}
102121
}

0 commit comments

Comments
 (0)