mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-27 04:24:07 +01:00
2ac2a5b0ba
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
123 lines
3 KiB
Go
123 lines
3 KiB
Go
// Copyright 2019 The Gitea Authors. All rights reserved.
|
|
// Copyright 2015 The Gogs Authors. All rights reserved.
|
|
// Use of this source code is governed by a MIT-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package git
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"net/url"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
var scpSyntax = regexp.MustCompile(`^([a-zA-Z0-9_]+@)?([a-zA-Z0-9._-]+):(.*)$`)
|
|
|
|
// SubModule submodule is a reference on git repository
|
|
type SubModule struct {
|
|
Name string
|
|
URL string
|
|
}
|
|
|
|
// SubModuleFile represents a file with submodule type.
|
|
type SubModuleFile struct {
|
|
*Commit
|
|
|
|
refURL string
|
|
refID string
|
|
}
|
|
|
|
// NewSubModuleFile create a new submodule file
|
|
func NewSubModuleFile(c *Commit, refURL, refID string) *SubModuleFile {
|
|
return &SubModuleFile{
|
|
Commit: c,
|
|
refURL: refURL,
|
|
refID: refID,
|
|
}
|
|
}
|
|
|
|
func getRefURL(refURL, urlPrefix, parentPath string) string {
|
|
if refURL == "" {
|
|
return ""
|
|
}
|
|
|
|
refURI := strings.TrimSuffix(refURL, ".git")
|
|
|
|
prefixURL, _ := url.Parse(urlPrefix)
|
|
urlPrefixHostname, _, err := net.SplitHostPort(prefixURL.Host)
|
|
if err != nil {
|
|
urlPrefixHostname = prefixURL.Host
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
if !strings.Contains(refURI, "://") {
|
|
// scp style syntax which contains *no* port number after the : (and is not parsed by net/url)
|
|
// ex: git@try.gitea.io:go-gitea/gitea
|
|
match := scpSyntax.FindAllStringSubmatch(refURI, -1)
|
|
if len(match) > 0 {
|
|
|
|
m := match[0]
|
|
refHostname := m[2]
|
|
path := m[3]
|
|
|
|
if !strings.HasPrefix(path, "/") {
|
|
path = "/" + path
|
|
}
|
|
|
|
if urlPrefixHostname == refHostname {
|
|
return prefixURL.Scheme + "://" + urlPrefixHostname + path
|
|
}
|
|
return "http://" + refHostname + path
|
|
}
|
|
}
|
|
|
|
ref, err := url.Parse(refURI)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
refHostname, _, err := net.SplitHostPort(ref.Host)
|
|
if err != nil {
|
|
refHostname = ref.Host
|
|
}
|
|
|
|
supportedSchemes := []string{"http", "https", "git", "ssh", "git+ssh"}
|
|
|
|
for _, scheme := range supportedSchemes {
|
|
if ref.Scheme == scheme {
|
|
if urlPrefixHostname == refHostname {
|
|
return prefixURL.Scheme + "://" + prefixURL.Host + 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
|
|
}
|
|
return ref.Scheme + "://" + ref.Host + ref.Path
|
|
} else {
|
|
return "http://" + refHostname + ref.Path
|
|
}
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
// RefURL guesses and returns reference URL.
|
|
func (sf *SubModuleFile) RefURL(urlPrefix string, parentPath string) string {
|
|
return getRefURL(sf.refURL, urlPrefix, parentPath)
|
|
}
|
|
|
|
// RefID returns reference ID.
|
|
func (sf *SubModuleFile) RefID() string {
|
|
return sf.refID
|
|
}
|