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  }