github.com/jingweno/gh@v2.1.1-0.20221007190738-04a7985fa9a1+incompatible/github/localrepo.go (about) 1 package github 2 3 import ( 4 "fmt" 5 "github.com/jingweno/gh/git" 6 ) 7 8 func LocalRepo() *GitHubRepo { 9 return &GitHubRepo{} 10 } 11 12 type GitHubRepo struct { 13 remotes []Remote 14 } 15 16 func (r *GitHubRepo) loadRemotes() error { 17 if r.remotes != nil { 18 return nil 19 } 20 21 remotes, err := Remotes() 22 if err != nil { 23 return err 24 } 25 r.remotes = remotes 26 27 return nil 28 } 29 30 func (r *GitHubRepo) RemoteByName(name string) (*Remote, error) { 31 r.loadRemotes() 32 33 for _, remote := range r.remotes { 34 if remote.Name == name { 35 return &remote, nil 36 } 37 } 38 39 return nil, fmt.Errorf("No git remote with name %s", name) 40 } 41 42 func (r *GitHubRepo) remotesForPublish(owner string) (remotes []Remote) { 43 r.loadRemotes() 44 45 if owner != "" { 46 for _, remote := range r.remotes { 47 p, e := remote.Project() 48 if e == nil && p.Owner == owner { 49 remotes = append(remotes, remote) 50 } 51 } 52 } 53 54 remote, err := r.RemoteByName("origin") 55 if err == nil { 56 remotes = append(remotes, *remote) 57 } 58 59 remote, err = r.RemoteByName("github") 60 if err == nil { 61 remotes = append(remotes, *remote) 62 } 63 64 remote, err = r.RemoteByName("upstream") 65 if err == nil { 66 remotes = append(remotes, *remote) 67 } 68 69 return 70 } 71 72 func (r *GitHubRepo) CurrentBranch() (branch *Branch, err error) { 73 head, err := git.Head() 74 if err != nil { 75 err = fmt.Errorf("Aborted: not currently on any branch.") 76 return 77 } 78 79 branch = &Branch{head} 80 return 81 } 82 83 func (r *GitHubRepo) MasterBranch() (branch *Branch) { 84 origin, e := r.RemoteByName("origin") 85 var name string 86 if e == nil { 87 name, _ = git.BranchAtRef("refs", "remotes", origin.Name, "HEAD") 88 } 89 90 if name == "" { 91 name = "refs/heads/master" 92 } 93 94 branch = &Branch{name} 95 96 return 97 } 98 99 func (r *GitHubRepo) RemoteBranchAndProject(owner string) (branch *Branch, project *Project, err error) { 100 project, err = r.MainProject() 101 if err != nil { 102 return 103 } 104 105 branch, err = r.CurrentBranch() 106 if err != nil { 107 return 108 } 109 110 pushDefault, _ := git.Config("push.default") 111 if pushDefault == "upstream" || pushDefault == "tracking" { 112 branch, err = branch.Upstream() 113 if err != nil { 114 return 115 } 116 } else { 117 shortName := branch.ShortName() 118 remotes := r.remotesForPublish(owner) 119 for _, remote := range remotes { 120 if git.HasFile("refs", "remotes", remote.Name, shortName) { 121 name := fmt.Sprintf("refs/remotes/%s/%s", remote.Name, shortName) 122 branch = &Branch{name} 123 break 124 } 125 } 126 } 127 128 if branch.IsRemote() { 129 remote, e := r.RemoteByName(branch.RemoteName()) 130 if e == nil { 131 project, err = remote.Project() 132 if err != nil { 133 return 134 } 135 } 136 } 137 138 return 139 } 140 141 func (r *GitHubRepo) MainProject() (project *Project, err error) { 142 origin, err := r.RemoteByName("origin") 143 if err != nil { 144 err = fmt.Errorf("Aborted: the origin remote doesn't point to a GitHub repository.") 145 return 146 } 147 148 project, err = origin.Project() 149 if err != nil { 150 err = fmt.Errorf("Aborted: the origin remote doesn't point to a GitHub repository.") 151 } 152 153 return 154 } 155 156 func (r *GitHubRepo) CurrentProject() (project *Project, err error) { 157 project, err = r.UpstreamProject() 158 if err != nil { 159 project, err = r.MainProject() 160 } 161 162 return 163 } 164 165 func (r *GitHubRepo) UpstreamProject() (project *Project, err error) { 166 currentBranch, err := r.CurrentBranch() 167 if err != nil { 168 return 169 } 170 171 upstream, err := currentBranch.Upstream() 172 if err != nil { 173 return 174 } 175 176 remote, err := r.RemoteByName(upstream.RemoteName()) 177 if err != nil { 178 return 179 } 180 181 project, err = remote.Project() 182 183 return 184 }