github.com/echohead/hub@v2.2.1+incompatible/github/localrepo.go (about) 1 package github 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/github/hub/git" 8 ) 9 10 func LocalRepo() (repo *GitHubRepo, err error) { 11 repo = &GitHubRepo{} 12 13 _, err = git.Dir() 14 if err != nil { 15 err = fmt.Errorf("fatal: Not a git repository") 16 return 17 } 18 19 return 20 } 21 22 type GitHubRepo struct { 23 remotes []Remote 24 } 25 26 func (r *GitHubRepo) loadRemotes() error { 27 if r.remotes != nil { 28 return nil 29 } 30 31 remotes, err := Remotes() 32 if err != nil { 33 return err 34 } 35 r.remotes = remotes 36 37 return nil 38 } 39 40 func (r *GitHubRepo) RemoteByName(name string) (*Remote, error) { 41 r.loadRemotes() 42 43 for _, remote := range r.remotes { 44 if remote.Name == name { 45 return &remote, nil 46 } 47 } 48 49 return nil, fmt.Errorf("No git remote with name %s", name) 50 } 51 52 func (r *GitHubRepo) remotesForPublish(owner string) (remotes []Remote) { 53 r.loadRemotes() 54 remotesMap := make(map[string]Remote) 55 56 if owner != "" { 57 for _, remote := range r.remotes { 58 p, e := remote.Project() 59 if e == nil && strings.ToLower(p.Owner) == owner { 60 remotesMap[remote.Name] = remote 61 } 62 } 63 } 64 65 names := OriginNamesInLookupOrder 66 for _, name := range names { 67 if _, ok := remotesMap[name]; ok { 68 continue 69 } 70 71 remote, err := r.RemoteByName(name) 72 if err == nil { 73 remotesMap[remote.Name] = *remote 74 } 75 } 76 77 for i := len(names) - 1; i >= 0; i-- { 78 name := names[i] 79 if remote, ok := remotesMap[name]; ok { 80 remotes = append(remotes, remote) 81 delete(remotesMap, name) 82 } 83 } 84 85 // anything other than names has higher priority 86 for _, remote := range remotesMap { 87 remotes = append([]Remote{remote}, remotes...) 88 } 89 90 return 91 } 92 93 func (r *GitHubRepo) CurrentBranch() (branch *Branch, err error) { 94 head, err := git.Head() 95 if err != nil { 96 err = fmt.Errorf("Aborted: not currently on any branch.") 97 return 98 } 99 100 branch = &Branch{r, head} 101 return 102 } 103 104 func (r *GitHubRepo) MasterBranch() (branch *Branch) { 105 origin, e := r.RemoteByName("origin") 106 var name string 107 if e == nil { 108 name, _ = git.BranchAtRef("refs", "remotes", origin.Name, "HEAD") 109 } 110 111 if name == "" { 112 name = "refs/heads/master" 113 } 114 115 branch = &Branch{r, name} 116 117 return 118 } 119 120 func (r *GitHubRepo) RemoteBranchAndProject(owner string, preferUpstream bool) (branch *Branch, project *Project, err error) { 121 r.loadRemotes() 122 123 for _, remote := range r.remotes { 124 if p, err := remote.Project(); err == nil { 125 project = p 126 break 127 } 128 } 129 130 branch, err = r.CurrentBranch() 131 if err != nil { 132 return 133 } 134 135 if project != nil { 136 branch = branch.PushTarget(owner, preferUpstream) 137 if branch != nil && branch.IsRemote() { 138 remote, e := r.RemoteByName(branch.RemoteName()) 139 if e == nil { 140 project, err = remote.Project() 141 if err != nil { 142 return 143 } 144 } 145 } 146 } 147 148 return 149 } 150 151 func (r *GitHubRepo) OriginRemote() (remote *Remote, err error) { 152 r.loadRemotes() 153 154 if len(r.remotes) > 0 { 155 remote = &r.remotes[0] 156 } 157 158 if remote == nil { 159 err = fmt.Errorf("Can't find git remote origin") 160 } 161 162 return 163 } 164 165 func (r *GitHubRepo) MainProject() (project *Project, err error) { 166 origin, err := r.OriginRemote() 167 if err != nil { 168 err = fmt.Errorf("Aborted: the origin remote doesn't point to a GitHub repository.") 169 170 return 171 } 172 173 project, err = origin.Project() 174 if err != nil { 175 err = fmt.Errorf("Aborted: the origin remote doesn't point to a GitHub repository.") 176 } 177 178 return 179 } 180 181 func (r *GitHubRepo) CurrentProject() (project *Project, err error) { 182 project, err = r.UpstreamProject() 183 if err != nil { 184 project, err = r.MainProject() 185 } 186 187 return 188 } 189 190 func (r *GitHubRepo) UpstreamProject() (project *Project, err error) { 191 currentBranch, err := r.CurrentBranch() 192 if err != nil { 193 return 194 } 195 196 upstream, err := currentBranch.Upstream() 197 if err != nil { 198 return 199 } 200 201 remote, err := r.RemoteByName(upstream.RemoteName()) 202 if err != nil { 203 return 204 } 205 206 project, err = remote.Project() 207 208 return 209 }