2019-06-03 18:11:20 +03:00
// Copyright 2019 The Gitea Authors. All rights reserved.
2016-11-04 01:16:01 +03:00
// Copyright 2015 The Gogs Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2016-11-04 01:16:01 +03:00
package git
2019-06-03 18:11:20 +03:00
import (
"fmt"
"net"
"net/url"
2020-04-22 13:34:50 +03:00
"path"
2019-06-03 18:11:20 +03:00
"regexp"
"strings"
)
var scpSyntax = regexp . MustCompile ( ` ^([a-zA-Z0-9_]+@)?([a-zA-Z0-9._-]+):(.*)$ ` )
2016-11-04 01:16:01 +03:00
2016-12-22 12:30:52 +03:00
// SubModule submodule is a reference on git repository
2016-11-04 01:16:01 +03:00
type SubModule struct {
Name string
URL string
}
// SubModuleFile represents a file with submodule type.
type SubModuleFile struct {
* Commit
refURL string
refID string
}
2016-12-22 12:30:52 +03:00
// NewSubModuleFile create a new submodule file
2016-11-04 01:16:01 +03:00
func NewSubModuleFile ( c * Commit , refURL , refID string ) * SubModuleFile {
return & SubModuleFile {
Commit : c ,
refURL : refURL ,
refID : refID ,
}
}
2020-09-08 03:08:10 +03:00
func getRefURL ( refURL , urlPrefix , repoFullName , sshDomain string ) string {
2019-02-03 06:35:17 +03:00
if refURL == "" {
2016-11-04 01:16:01 +03:00
return ""
}
2019-06-03 18:11:20 +03:00
refURI := strings . TrimSuffix ( refURL , ".git" )
2016-11-04 01:16:01 +03:00
2019-06-03 18:11:20 +03:00
prefixURL , _ := url . Parse ( urlPrefix )
urlPrefixHostname , _ , err := net . SplitHostPort ( prefixURL . Host )
if err != nil {
urlPrefixHostname = prefixURL . Host
2016-11-04 01:16:01 +03:00
}
2021-10-17 22:47:12 +03:00
urlPrefix = strings . TrimSuffix ( urlPrefix , "/" )
2020-05-07 17:25:52 +03:00
2020-04-22 13:34:50 +03:00
// FIXME: Need to consider branch - which will require changes in modules/git/commit.go:GetSubModules
2016-11-04 01:16:01 +03:00
// Relative url prefix check (according to git submodule documentation)
2019-06-03 18:11:20 +03:00
if strings . HasPrefix ( refURI , "./" ) || strings . HasPrefix ( refURI , "../" ) {
2020-05-07 17:25:52 +03:00
return urlPrefix + path . Clean ( path . Join ( "/" , repoFullName , refURI ) )
2016-11-04 01:16:01 +03:00
}
2019-06-03 18:11:20 +03:00
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 {
2016-11-04 01:16:01 +03:00
2019-06-03 18:11:20 +03:00
m := match [ 0 ]
refHostname := m [ 2 ]
2020-04-22 13:34:50 +03:00
pth := m [ 3 ]
2019-06-03 18:11:20 +03:00
2020-04-22 13:34:50 +03:00
if ! strings . HasPrefix ( pth , "/" ) {
pth = "/" + pth
2019-06-03 18:11:20 +03:00
}
2020-09-08 03:08:10 +03:00
if urlPrefixHostname == refHostname || refHostname == sshDomain {
2020-05-07 17:25:52 +03:00
return urlPrefix + path . Clean ( path . Join ( "/" , pth ) )
2019-06-03 18:11:20 +03:00
}
2020-04-22 13:34:50 +03:00
return "http://" + refHostname + pth
2016-11-04 01:16:01 +03:00
}
2019-06-03 18:11:20 +03:00
}
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 {
2020-08-13 07:19:04 +03:00
if ref . Scheme == "http" || ref . Scheme == "https" {
2019-06-03 18:11:20 +03:00
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
2020-09-08 03:08:10 +03:00
} else if urlPrefixHostname == refHostname || refHostname == sshDomain {
2020-08-13 07:19:04 +03:00
return urlPrefix + path . Clean ( path . Join ( "/" , ref . Path ) )
2019-06-03 18:11:20 +03:00
}
2023-10-24 05:54:59 +03:00
return "http://" + refHostname + ref . Path
2019-02-03 06:35:17 +03:00
}
2016-11-04 01:16:01 +03:00
}
2019-06-03 18:11:20 +03:00
return ""
2016-11-04 01:16:01 +03:00
}
2019-02-03 06:35:17 +03:00
// RefURL guesses and returns reference URL.
2020-09-08 03:08:10 +03:00
func ( sf * SubModuleFile ) RefURL ( urlPrefix , repoFullName , sshDomain string ) string {
return getRefURL ( sf . refURL , urlPrefix , repoFullName , sshDomain )
2019-02-03 06:35:17 +03:00
}
2016-11-04 01:16:01 +03:00
// RefID returns reference ID.
func ( sf * SubModuleFile ) RefID ( ) string {
return sf . refID
}