github.com/pengwynn/gh@v1.0.1-0.20140118055701-14327ca3942e/github/project.go (about)

     1  package github
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"github.com/jingweno/gh/git"
     7  	"github.com/jingweno/gh/utils"
     8  	"net/url"
     9  	"os"
    10  	"regexp"
    11  	"strings"
    12  )
    13  
    14  type Project struct {
    15  	Name  string
    16  	Owner string
    17  	Host  string
    18  }
    19  
    20  func (p Project) String() string {
    21  	return fmt.Sprintf("%s/%s", p.Owner, p.Name)
    22  }
    23  
    24  func (p *Project) WebURL(name, owner, path string) string {
    25  	if owner == "" {
    26  		owner = p.Owner
    27  	}
    28  	if name == "" {
    29  		name = p.Name
    30  	}
    31  
    32  	ownerWithName := fmt.Sprintf("%s/%s", owner, name)
    33  	if strings.Contains(ownerWithName, ".wiki") {
    34  		ownerWithName = strings.TrimSuffix(ownerWithName, ".wiki")
    35  		if path != "wiki" {
    36  			if strings.HasPrefix(path, "commits") {
    37  				path = "_history"
    38  			} else if path != "" {
    39  				path = fmt.Sprintf("_%s", path)
    40  			}
    41  
    42  			if path != "" {
    43  				path = utils.ConcatPaths("wiki", path)
    44  			} else {
    45  				path = "wiki"
    46  			}
    47  		}
    48  	}
    49  
    50  	url := fmt.Sprintf("https://%s", utils.ConcatPaths(p.Host, ownerWithName))
    51  	if path != "" {
    52  		url = utils.ConcatPaths(url, path)
    53  	}
    54  
    55  	return url
    56  }
    57  
    58  func (p *Project) GitURL(name, owner string, isSSH bool) (url string) {
    59  	if name == "" {
    60  		name = p.Name
    61  	}
    62  	if owner == "" {
    63  		owner = p.Owner
    64  	}
    65  
    66  	host := rawHost(p.Host)
    67  
    68  	if useHttpProtocol() {
    69  		url = fmt.Sprintf("https://%s/%s/%s.git", host, owner, name)
    70  	} else if isSSH {
    71  		url = fmt.Sprintf("git@%s:%s/%s.git", host, owner, name)
    72  	} else {
    73  		url = fmt.Sprintf("git://%s/%s/%s.git", host, owner, name)
    74  	}
    75  
    76  	return url
    77  }
    78  
    79  // Remove the scheme from host when the credential url is absolute.
    80  func rawHost(host string) string {
    81  	u, err := url.Parse(host)
    82  	utils.Check(err)
    83  
    84  	if u.IsAbs() {
    85  		return u.Host
    86  	} else {
    87  		return u.Path
    88  	}
    89  }
    90  
    91  func useHttpProtocol() bool {
    92  	https := os.Getenv("GH_PROTOCOL")
    93  	if https == "" {
    94  		https, _ = git.Config("gh.protocol")
    95  	}
    96  
    97  	return https == "https"
    98  }
    99  
   100  func NewProjectFromURL(url *url.URL) (p *Project, err error) {
   101  	if !knownHosts().Include(url.Host) {
   102  		err = fmt.Errorf("Invalid GitHub URL: %s", url)
   103  		return
   104  	}
   105  
   106  	parts := strings.SplitN(url.Path, "/", 4)
   107  	if len(parts) <= 2 {
   108  		err = fmt.Errorf("Invalid GitHub URL: %s", url)
   109  		return
   110  	}
   111  
   112  	name := strings.TrimSuffix(parts[2], ".git")
   113  	p = NewProject(parts[1], name, url.Host)
   114  
   115  	return
   116  }
   117  
   118  func NewProject(owner, name, host string) *Project {
   119  	if strings.Contains(owner, "/") {
   120  		result := strings.SplitN(owner, "/", 2)
   121  		owner = result[0]
   122  		if name == "" {
   123  			name = result[1]
   124  		}
   125  	} else if strings.Contains(name, "/") {
   126  		result := strings.SplitN(name, "/", 2)
   127  		if owner == "" {
   128  			owner = result[0]
   129  		}
   130  		name = result[1]
   131  	}
   132  
   133  	if host == "" {
   134  		host = DefaultHost()
   135  	}
   136  
   137  	if owner == "" {
   138  		c := CurrentConfigs().PromptFor(host)
   139  		owner = c.User
   140  	}
   141  
   142  	if name == "" {
   143  		name, _ = utils.DirName()
   144  	}
   145  
   146  	return &Project{Name: name, Owner: owner, Host: host}
   147  }
   148  
   149  func parseOwnerAndName(remote string) (owner string, name string) {
   150  	url, err := mustMatchGitHubURL(remote)
   151  	utils.Check(err)
   152  
   153  	return url[1], url[2]
   154  }
   155  
   156  func MatchURL(url string) []string {
   157  	httpRegex := regexp.MustCompile("https://github\\.com/(.+)/(.+?)(\\.git|$)")
   158  	if httpRegex.MatchString(url) {
   159  		return httpRegex.FindStringSubmatch(url)
   160  	}
   161  
   162  	readOnlyRegex := regexp.MustCompile("git://.*github\\.com/(.+)/(.+?)(\\.git|$)")
   163  	if readOnlyRegex.MatchString(url) {
   164  		return readOnlyRegex.FindStringSubmatch(url)
   165  	}
   166  
   167  	sshRegex := regexp.MustCompile("git@github\\.com:(.+)/(.+?)(\\.git|$)")
   168  	if sshRegex.MatchString(url) {
   169  		return sshRegex.FindStringSubmatch(url)
   170  	}
   171  
   172  	return nil
   173  }
   174  
   175  func mustMatchGitHubURL(url string) ([]string, error) {
   176  	githubURL := MatchURL(url)
   177  	if githubURL == nil {
   178  		return nil, errors.New("The origin remote doesn't point to a GitHub repository: " + url)
   179  	}
   180  
   181  	return githubURL, nil
   182  }