1package lfs23import (4 "fmt"5 "net/url"6 "strings"7)89// Endpoint is a Git LFS endpoint.10type Endpoint = *url.URL1112// NewEndpoint returns a new Git LFS endpoint.13func NewEndpoint(rawurl string) (Endpoint, error) {14 u, err := url.Parse(rawurl)15 if err != nil {16 e, err := endpointFromBareSSH(rawurl)17 if err != nil {18 return nil, err19 }20 u = e21 }2223 u.Path = strings.TrimSuffix(u.Path, "/")2425 switch u.Scheme {26 case "git":27 // Use https for git:// URLs and strip the port if it exists.28 u.Scheme = "https"29 if u.Port() != "" {30 u.Host = u.Hostname()31 }32 fallthrough33 case "http", "https":34 if strings.HasSuffix(u.Path, ".git") {35 u.Path += "/info/lfs"36 } else {37 u.Path += ".git/info/lfs"38 }39 case "ssh", "git+ssh", "ssh+git":40 default:41 return nil, fmt.Errorf("unknown url: %s", rawurl)42 }4344 return u, nil45}4647// endpointFromBareSSH creates a new endpoint from a bare ssh repo.48//49// user@host.com:path/to/repo.git or50// [user@host.com:port]:path/to/repo.git51func endpointFromBareSSH(rawurl string) (*url.URL, error) {52 parts := strings.Split(rawurl, ":")53 partsLen := len(parts)54 if partsLen < 2 {55 return url.Parse(rawurl)56 }5758 // Treat presence of ':' as a bare URL59 var newPath string60 if len(parts) > 2 { // port included; really should only ever be 3 parts61 // Correctly handle [host:port]:path URLs62 parts[0] = strings.TrimPrefix(parts[0], "[")63 parts[1] = strings.TrimSuffix(parts[1], "]")64 newPath = fmt.Sprintf("%v:%v", parts[0], strings.Join(parts[1:], "/"))65 } else {66 newPath = strings.Join(parts, "/")67 }68 newrawurl := fmt.Sprintf("ssh://%v", newPath)69 return url.Parse(newrawurl)70}