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  }