From 4a6765fba2dec636b8d78795bd6f8ee6df867c74 Mon Sep 17 00:00:00 2001
From: zeripath <art27@cantab.net>
Date: Wed, 22 Apr 2020 13:37:52 +0100
Subject: [PATCH] Fix submodule paths when AppSubUrl is not root (#11098)
 (#11176)

Backport #11098

Fix #11002

Signed-off-by: Andrew Thornton <art27@cantab.net>
---
 modules/git/submodule.go      | 27 ++++++++++++---------------
 modules/git/submodule_test.go | 28 ++++++++++++++--------------
 templates/repo/view_list.tmpl |  2 +-
 3 files changed, 27 insertions(+), 30 deletions(-)

diff --git a/modules/git/submodule.go b/modules/git/submodule.go
index 6fc2e2444f..2527eac810 100644
--- a/modules/git/submodule.go
+++ b/modules/git/submodule.go
@@ -9,6 +9,7 @@ import (
 	"fmt"
 	"net"
 	"net/url"
+	"path"
 	"regexp"
 	"strings"
 )
@@ -38,7 +39,7 @@ func NewSubModuleFile(c *Commit, refURL, refID string) *SubModuleFile {
 	}
 }
 
-func getRefURL(refURL, urlPrefix, parentPath string) string {
+func getRefURL(refURL, urlPrefix, repoFullName string) string {
 	if refURL == "" {
 		return ""
 	}
@@ -51,14 +52,10 @@ func getRefURL(refURL, urlPrefix, parentPath string) string {
 		urlPrefixHostname = prefixURL.Host
 	}
 
+	// FIXME: Need to consider branch - which will require changes in modules/git/commit.go:GetSubModules
 	// Relative url prefix check (according to git submodule documentation)
 	if strings.HasPrefix(refURI, "./") || strings.HasPrefix(refURI, "../") {
-		// ...construct and return correct submodule url here...
-		idx := strings.Index(parentPath, "/src/")
-		if idx == -1 {
-			return refURI
-		}
-		return strings.TrimSuffix(urlPrefix, "/") + parentPath[:idx] + "/" + refURI
+		return urlPrefix + path.Clean(path.Join(repoFullName, refURI))
 	}
 
 	if !strings.Contains(refURI, "://") {
@@ -69,16 +66,16 @@ func getRefURL(refURL, urlPrefix, parentPath string) string {
 
 			m := match[0]
 			refHostname := m[2]
-			path := m[3]
+			pth := m[3]
 
-			if !strings.HasPrefix(path, "/") {
-				path = "/" + path
+			if !strings.HasPrefix(pth, "/") {
+				pth = "/" + pth
 			}
 
 			if urlPrefixHostname == refHostname {
-				return prefixURL.Scheme + "://" + urlPrefixHostname + path
+				return prefixURL.Scheme + "://" + urlPrefixHostname + path.Join(prefixURL.Path, path.Clean(pth))
 			}
-			return "http://" + refHostname + path
+			return "http://" + refHostname + pth
 		}
 	}
 
@@ -97,7 +94,7 @@ func getRefURL(refURL, urlPrefix, parentPath string) string {
 	for _, scheme := range supportedSchemes {
 		if ref.Scheme == scheme {
 			if urlPrefixHostname == refHostname {
-				return prefixURL.Scheme + "://" + prefixURL.Host + ref.Path
+				return prefixURL.Scheme + "://" + prefixURL.Host + path.Join(prefixURL.Path, ref.Path)
 			} else if ref.Scheme == "http" || ref.Scheme == "https" {
 				if len(ref.User.Username()) > 0 {
 					return ref.Scheme + "://" + fmt.Sprintf("%v", ref.User) + "@" + ref.Host + ref.Path
@@ -113,8 +110,8 @@ func getRefURL(refURL, urlPrefix, parentPath string) string {
 }
 
 // RefURL guesses and returns reference URL.
-func (sf *SubModuleFile) RefURL(urlPrefix string, parentPath string) string {
-	return getRefURL(sf.refURL, urlPrefix, parentPath)
+func (sf *SubModuleFile) RefURL(urlPrefix string, repoFullName string) string {
+	return getRefURL(sf.refURL, urlPrefix, repoFullName)
 }
 
 // RefID returns reference ID.
diff --git a/modules/git/submodule_test.go b/modules/git/submodule_test.go
index fd6c2aa955..458c547dcb 100644
--- a/modules/git/submodule_test.go
+++ b/modules/git/submodule_test.go
@@ -17,21 +17,21 @@ func TestGetRefURL(t *testing.T) {
 		parentPath string
 		expect     string
 	}{
-		{"git://github.com/user1/repo1", "/", "/", "http://github.com/user1/repo1"},
-		{"https://localhost/user1/repo1.git", "/", "/", "https://localhost/user1/repo1"},
-		{"http://localhost/user1/repo1.git", "/", "/", "http://localhost/user1/repo1"},
-		{"git@github.com:user1/repo1.git", "/", "/", "http://github.com/user1/repo1"},
-		{"ssh://git@git.zefie.net:2222/zefie/lge_g6_kernel_scripts.git", "/", "/", "http://git.zefie.net/zefie/lge_g6_kernel_scripts"},
-		{"git@git.zefie.net:2222/zefie/lge_g6_kernel_scripts.git", "/", "/", "http://git.zefie.net/2222/zefie/lge_g6_kernel_scripts"},
-		{"git@try.gitea.io:go-gitea/gitea", "https://try.gitea.io/go-gitea/gitea", "/", "https://try.gitea.io/go-gitea/gitea"},
-		{"ssh://git@try.gitea.io:9999/go-gitea/gitea", "https://try.gitea.io/go-gitea/gitea", "/", "https://try.gitea.io/go-gitea/gitea"},
-		{"git://git@try.gitea.io:9999/go-gitea/gitea", "https://try.gitea.io/go-gitea/log", "/", "https://try.gitea.io/go-gitea/gitea"},
-		{"ssh://git@127.0.0.1:9999/go-gitea/gitea", "https://127.0.0.1:3000/go-gitea/log", "/", "https://127.0.0.1:3000/go-gitea/gitea"},
-		{"https://gitea.com:3000/user1/repo1.git", "https://127.0.0.1:3000/go-gitea/gitea", "/", "https://gitea.com:3000/user1/repo1"},
-		{"https://username:password@github.com/username/repository.git", "/", "/", "https://username:password@github.com/username/repository"},
+		{"git://github.com/user1/repo1", "/", "user1/repo2", "http://github.com/user1/repo1"},
+		{"https://localhost/user1/repo1.git", "/", "user1/repo2", "https://localhost/user1/repo1"},
+		{"http://localhost/user1/repo1.git", "/", "owner/reponame", "http://localhost/user1/repo1"},
+		{"git@github.com:user1/repo1.git", "/", "owner/reponame", "http://github.com/user1/repo1"},
+		{"ssh://git@git.zefie.net:2222/zefie/lge_g6_kernel_scripts.git", "/", "zefie/lge_g6_kernel", "http://git.zefie.net/zefie/lge_g6_kernel_scripts"},
+		{"git@git.zefie.net:2222/zefie/lge_g6_kernel_scripts.git", "/", "zefie/lge_g6_kernel", "http://git.zefie.net/2222/zefie/lge_g6_kernel_scripts"},
+		{"git@try.gitea.io:go-gitea/gitea", "https://try.gitea.io/", "go-gitea/sdk", "https://try.gitea.io/go-gitea/gitea"},
+		{"ssh://git@try.gitea.io:9999/go-gitea/gitea", "https://try.gitea.io/", "go-gitea/sdk", "https://try.gitea.io/go-gitea/gitea"},
+		{"git://git@try.gitea.io:9999/go-gitea/gitea", "https://try.gitea.io/", "go-gitea/sdk", "https://try.gitea.io/go-gitea/gitea"},
+		{"ssh://git@127.0.0.1:9999/go-gitea/gitea", "https://127.0.0.1:3000/", "go-gitea/sdk", "https://127.0.0.1:3000/go-gitea/gitea"},
+		{"https://gitea.com:3000/user1/repo1.git", "https://127.0.0.1:3000/", "user/repo2", "https://gitea.com:3000/user1/repo1"},
+		{"https://username:password@github.com/username/repository.git", "/", "username/repository2", "https://username:password@github.com/username/repository"},
 		{"somethingbad", "https://127.0.0.1:3000/go-gitea/gitea", "/", ""},
-		{"git@localhost:user/repo", "https://localhost/user/repo2", "/", "https://localhost/user/repo"},
-		{"../path/to/repo.git/", "https://localhost/user/repo2/src/branch/master/test", "/", "../path/to/repo.git/"},
+		{"git@localhost:user/repo", "https://localhost/", "user2/repo1", "https://localhost/user/repo"},
+		{"../path/to/repo.git/", "https://localhost/", "user/repo2", "https://localhost/user/path/to/repo.git"},
 	}
 
 	for _, kase := range kases {
diff --git a/templates/repo/view_list.tmpl b/templates/repo/view_list.tmpl
index d3fb914756..5f2211385a 100644
--- a/templates/repo/view_list.tmpl
+++ b/templates/repo/view_list.tmpl
@@ -64,7 +64,7 @@
 					<td>
 						<span class="truncate">
 							<span class="octicon octicon-file-submodule"></span>
-							{{$refURL := $commit.RefURL AppUrl $.BranchLink}}
+							{{$refURL := $commit.RefURL AppUrl $.Repository.FullName}}
 							{{if $refURL}}
 								<a href="{{$refURL}}">{{$entry.Name}}</a> @ <a href="{{$refURL}}/commit/{{$commit.RefID}}">{{ShortSha $commit.RefID}}</a>
 							{{else}}