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