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.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
2019-06-03 18:11:20 +03:00
import (
"fmt"
"net"
"net/url"
"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 ,
}
}
2019-02-03 06:35:17 +03:00
func getRefURL ( refURL , urlPrefix , parentPath string ) string {
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
}
// Relative url prefix check (according to git submodule documentation)
2019-06-03 18:11:20 +03:00
if strings . HasPrefix ( refURI , "./" ) || strings . HasPrefix ( refURI , "../" ) {
2016-11-04 01:16:01 +03:00
// ...construct and return correct submodule url here...
idx := strings . Index ( parentPath , "/src/" )
if idx == - 1 {
2019-06-03 18:11:20 +03:00
return refURI
2016-11-04 01:16:01 +03:00
}
2019-06-03 18:11:20 +03:00
return strings . TrimSuffix ( urlPrefix , "/" ) + parentPath [ : idx ] + "/" + 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 ]
path := m [ 3 ]
if ! strings . HasPrefix ( path , "/" ) {
path = "/" + path
}
if urlPrefixHostname == refHostname {
return prefixURL . Scheme + "://" + urlPrefixHostname + path
}
return "http://" + refHostname + path
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 {
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
}
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.
func ( sf * SubModuleFile ) RefURL ( urlPrefix string , parentPath string ) string {
return getRefURL ( sf . refURL , urlPrefix , parentPath )
}
2016-11-04 01:16:01 +03:00
// RefID returns reference ID.
func ( sf * SubModuleFile ) RefID ( ) string {
return sf . refID
}