github.com/echohead/hub@v2.2.1+incompatible/github/project.go (about) 1 package github 2 3 import ( 4 "fmt" 5 "net/url" 6 "os" 7 "strings" 8 9 "github.com/github/hub/git" 10 "github.com/github/hub/utils" 11 ) 12 13 type Project struct { 14 Name string 15 Owner string 16 Host string 17 Protocol 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) SameAs(other *Project) bool { 25 return p.Owner == other.Owner && p.Name == other.Name && p.Host == other.Host 26 } 27 28 func (p *Project) WebURL(name, owner, path string) string { 29 if owner == "" { 30 owner = p.Owner 31 } 32 if name == "" { 33 name = p.Name 34 } 35 36 ownerWithName := fmt.Sprintf("%s/%s", owner, name) 37 if strings.Contains(ownerWithName, ".wiki") { 38 ownerWithName = strings.TrimSuffix(ownerWithName, ".wiki") 39 if path != "wiki" { 40 if strings.HasPrefix(path, "commits") { 41 path = "_history" 42 } else if path != "" { 43 path = fmt.Sprintf("_%s", path) 44 } 45 46 if path != "" { 47 path = utils.ConcatPaths("wiki", path) 48 } else { 49 path = "wiki" 50 } 51 } 52 } 53 54 url := fmt.Sprintf("%s://%s", p.Protocol, utils.ConcatPaths(p.Host, ownerWithName)) 55 if path != "" { 56 url = utils.ConcatPaths(url, path) 57 } 58 59 return url 60 } 61 62 func (p *Project) GitURL(name, owner string, isSSH bool) (url string) { 63 if name == "" { 64 name = p.Name 65 } 66 if owner == "" { 67 owner = p.Owner 68 } 69 70 host := rawHost(p.Host) 71 72 if useHttpProtocol() { 73 url = fmt.Sprintf("https://%s/%s/%s.git", host, owner, name) 74 } else if isSSH { 75 url = fmt.Sprintf("git@%s:%s/%s.git", host, owner, name) 76 } else { 77 url = fmt.Sprintf("git://%s/%s/%s.git", host, owner, name) 78 } 79 80 return url 81 } 82 83 // Remove the scheme from host when the host url is absolute. 84 func rawHost(host string) string { 85 u, err := url.Parse(host) 86 utils.Check(err) 87 88 if u.IsAbs() { 89 return u.Host 90 } else { 91 return u.Path 92 } 93 } 94 95 func useHttpProtocol() bool { 96 https := os.Getenv("HUB_PROTOCOL") 97 if https == "" { 98 https, _ = git.Config("hub.protocol") 99 } 100 101 return https == "https" 102 } 103 104 func NewProjectFromURL(url *url.URL) (p *Project, err error) { 105 if !knownGitHubHosts().Include(url.Host) { 106 err = fmt.Errorf("Invalid GitHub URL: %s", url) 107 return 108 } 109 110 parts := strings.SplitN(url.Path, "/", 4) 111 if len(parts) <= 2 { 112 err = fmt.Errorf("Invalid GitHub URL: %s", url) 113 return 114 } 115 116 name := strings.TrimSuffix(parts[2], ".git") 117 p = newProject(parts[1], name, url.Host, url.Scheme) 118 119 return 120 } 121 122 func NewProject(owner, name, host string) *Project { 123 return newProject(owner, name, host, "") 124 } 125 126 func newProject(owner, name, host, protocol string) *Project { 127 if strings.Contains(owner, "/") { 128 result := strings.SplitN(owner, "/", 2) 129 owner = result[0] 130 if name == "" { 131 name = result[1] 132 } 133 } else if strings.Contains(name, "/") { 134 result := strings.SplitN(name, "/", 2) 135 if owner == "" { 136 owner = result[0] 137 } 138 name = result[1] 139 } 140 141 if host == "" { 142 host = DefaultGitHubHost() 143 } 144 if host == "ssh.github.com" { 145 host = "github.com" 146 } 147 148 if protocol != "http" && protocol != "https" { 149 protocol = "" 150 } 151 if protocol == "" { 152 h := CurrentConfig().Find(host) 153 if h != nil { 154 protocol = h.Protocol 155 } 156 } 157 if protocol == "" { 158 protocol = "https" 159 } 160 161 if owner == "" { 162 h := CurrentConfig().Find(host) 163 if h != nil { 164 owner = h.User 165 } 166 } 167 168 if name == "" { 169 name, _ = utils.DirName() 170 } 171 172 return &Project{ 173 Name: name, 174 Owner: owner, 175 Host: host, 176 Protocol: protocol, 177 } 178 }