github.com/stffabi/git-lfs@v2.3.5-0.20180214015214-8eeaa8d88902+incompatible/lfsapi/endpoint.go (about) 1 package lfsapi 2 3 import ( 4 "fmt" 5 "net/url" 6 "regexp" 7 "strings" 8 ) 9 10 const UrlUnknown = "<unknown>" 11 12 // An Endpoint describes how to access a Git LFS server. 13 type Endpoint struct { 14 Url string 15 SshUserAndHost string 16 SshPath string 17 SshPort string 18 Operation string 19 } 20 21 func endpointOperation(e Endpoint, method string) string { 22 if len(e.Operation) > 0 { 23 return e.Operation 24 } 25 26 switch method { 27 case "GET", "HEAD": 28 return "download" 29 default: 30 return "upload" 31 } 32 } 33 34 // endpointFromBareSshUrl constructs a new endpoint from a bare SSH URL: 35 // 36 // user@host.com:path/to/repo.git 37 // 38 func endpointFromBareSshUrl(rawurl string) Endpoint { 39 parts := strings.Split(rawurl, ":") 40 partsLen := len(parts) 41 if partsLen < 2 { 42 return Endpoint{Url: rawurl} 43 } 44 45 // Treat presence of ':' as a bare URL 46 var newPath string 47 if len(parts) > 2 { // port included; really should only ever be 3 parts 48 newPath = fmt.Sprintf("%v:%v", parts[0], strings.Join(parts[1:], "/")) 49 } else { 50 newPath = strings.Join(parts, "/") 51 } 52 newrawurl := fmt.Sprintf("ssh://%v", newPath) 53 newu, err := url.Parse(newrawurl) 54 if err != nil { 55 return Endpoint{Url: UrlUnknown} 56 } 57 58 return endpointFromSshUrl(newu) 59 } 60 61 // endpointFromSshUrl constructs a new endpoint from an ssh:// URL 62 func endpointFromSshUrl(u *url.URL) Endpoint { 63 var endpoint Endpoint 64 // Pull out port now, we need it separately for SSH 65 regex := regexp.MustCompile(`^([^\:]+)(?:\:(\d+))?$`) 66 match := regex.FindStringSubmatch(u.Host) 67 if match == nil || len(match) < 2 { 68 endpoint.Url = UrlUnknown 69 return endpoint 70 } 71 72 host := match[1] 73 if u.User != nil && u.User.Username() != "" { 74 endpoint.SshUserAndHost = fmt.Sprintf("%s@%s", u.User.Username(), host) 75 } else { 76 endpoint.SshUserAndHost = host 77 } 78 79 if len(match) > 2 { 80 endpoint.SshPort = match[2] 81 } 82 83 // u.Path includes a preceding '/', strip off manually 84 // rooted paths in the URL will be '//path/to/blah' 85 // this is just how Go's URL parsing works 86 if strings.HasPrefix(u.Path, "/") { 87 endpoint.SshPath = u.Path[1:] 88 } else { 89 endpoint.SshPath = u.Path 90 } 91 92 // Fallback URL for using HTTPS while still using SSH for git 93 // u.Host includes host & port so can't use SSH port 94 endpoint.Url = fmt.Sprintf("https://%s%s", host, u.Path) 95 96 return endpoint 97 } 98 99 // Construct a new endpoint from a HTTP URL 100 func endpointFromHttpUrl(u *url.URL) Endpoint { 101 // just pass this straight through 102 return Endpoint{Url: u.String()} 103 } 104 105 func endpointFromGitUrl(u *url.URL, e *endpointGitFinder) Endpoint { 106 u.Scheme = e.gitProtocol 107 return Endpoint{Url: u.String()} 108 }