git-lfs/config/url_config.go

141 lines
3.0 KiB
Go

package config
import (
"fmt"
"net/url"
"strings"
)
type URLConfig struct {
git Environment
}
func NewURLConfig(git Environment) *URLConfig {
if git == nil {
git = EnvironmentOf(make(mapFetcher))
}
return &URLConfig{
git: git,
}
}
// Get retrieves a `http.{url}.{key}` for the given key and urls, following the
// rules in https://git-scm.com/docs/git-config#git-config-httplturlgt.
// The value for `http.{key}` is returned as a fallback if no config keys are
// set for the given urls.
func (c *URLConfig) Get(prefix, rawurl, key string) (string, bool) {
if c == nil {
return "", false
}
key = strings.ToLower(key)
prefix = strings.ToLower(prefix)
if v := c.getAll(prefix, rawurl, key); len(v) > 0 {
return v[len(v)-1], true
}
return c.git.Get(strings.Join([]string{prefix, key}, "."))
}
func (c *URLConfig) GetAll(prefix, rawurl, key string) []string {
if c == nil {
return nil
}
key = strings.ToLower(key)
prefix = strings.ToLower(prefix)
if v := c.getAll(prefix, rawurl, key); len(v) > 0 {
return v
}
return c.git.GetAll(strings.Join([]string{prefix, key}, "."))
}
func (c *URLConfig) getAll(prefix, rawurl, key string) []string {
hosts, paths := c.hostsAndPaths(rawurl)
for i := len(paths); i > 0; i-- {
for _, host := range hosts {
path := strings.Join(paths[:i], slash)
if v := c.git.GetAll(fmt.Sprintf("%s.%s/%s.%s", prefix, host, path, key)); len(v) > 0 {
return v
}
if v := c.git.GetAll(fmt.Sprintf("%s.%s/%s/.%s", prefix, host, path, key)); len(v) > 0 {
return v
}
if isDefaultLFSUrl(path, paths, i) {
path = path[0 : len(path)-4]
if v := c.git.GetAll(fmt.Sprintf("%s.%s/%s.%s", prefix, host, path, key)); len(v) > 0 {
return v
}
}
}
}
for _, host := range hosts {
if v := c.git.GetAll(fmt.Sprintf("%s.%s.%s", prefix, host, key)); len(v) > 0 {
return v
}
if v := c.git.GetAll(fmt.Sprintf("%s.%s/.%s", prefix, host, key)); len(v) > 0 {
return v
}
}
return nil
}
func (c *URLConfig) hostsAndPaths(rawurl string) (hosts, paths []string) {
u, err := url.Parse(rawurl)
if err != nil {
return nil, nil
}
return c.hosts(u), c.paths(u.Path)
}
func (c *URLConfig) hosts(u *url.URL) []string {
hosts := make([]string, 0, 1)
if u.User != nil {
hosts = append(hosts, fmt.Sprintf("%s://%s@%s", u.Scheme, u.User.Username(), u.Host))
}
hosts = append(hosts, fmt.Sprintf("%s://%s", u.Scheme, u.Host))
return hosts
}
func (c *URLConfig) paths(path string) []string {
pLen := len(path)
if pLen <= 2 {
return nil
}
end := pLen
if strings.HasSuffix(path, slash) {
end--
}
return strings.Split(path[1:end], slash)
}
const (
gitExt = ".git"
infoPart = "info"
lfsPart = "lfs"
slash = "/"
)
func isDefaultLFSUrl(path string, parts []string, index int) bool {
if len(path) < 5 {
return false // shorter than ".git"
}
if !strings.HasSuffix(path, gitExt) {
return false
}
if index > len(parts)-2 {
return false
}
return parts[index] == infoPart && parts[index+1] == lfsPart
}