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  }