checkoutRemoteDefaultBranch ensures the working tree is checked out to the remote's default branch (the branch target of origin/HEAD). If the local branch does not exist it will be created to track the remote branch.
(repo *git.Repository, worktree *git.Worktree, authMethod transport.AuthMethod)
| 751 | // (the branch target of origin/HEAD). If the local branch does not exist it will be created to track |
| 752 | // the remote branch. |
| 753 | func checkoutRemoteDefaultBranch(repo *git.Repository, worktree *git.Worktree, authMethod transport.AuthMethod) error { |
| 754 | resolved, err := resolveRemoteDefaultBranch(repo, authMethod) |
| 755 | if err != nil { |
| 756 | return err |
| 757 | } |
| 758 | branchRefName := resolved.name |
| 759 | // If HEAD already points to the desired branch, nothing to do. |
| 760 | headRef, errHead := repo.Head() |
| 761 | if errHead == nil && headRef.Name() == branchRefName { |
| 762 | return nil |
| 763 | } |
| 764 | // If local branch exists, attempt a checkout |
| 765 | if _, err := repo.Reference(branchRefName, true); err == nil { |
| 766 | if err := worktree.Checkout(&git.CheckoutOptions{Branch: branchRefName}); err != nil { |
| 767 | return fmt.Errorf("checkout branch %s: %w", branchRefName.String(), err) |
| 768 | } |
| 769 | return nil |
| 770 | } |
| 771 | // Try to find the corresponding remote tracking ref (refs/remotes/origin/<name>) |
| 772 | branchShort := strings.TrimPrefix(branchRefName.String(), "refs/heads/") |
| 773 | remoteRefName := plumbing.ReferenceName("refs/remotes/origin/" + branchShort) |
| 774 | hash := resolved.hash |
| 775 | if remoteRef, err := repo.Reference(remoteRefName, true); err == nil { |
| 776 | hash = remoteRef.Hash() |
| 777 | } else if err != nil && !errors.Is(err, plumbing.ErrReferenceNotFound) { |
| 778 | return fmt.Errorf("checkout remote default: remote ref %s: %w", remoteRefName.String(), err) |
| 779 | } |
| 780 | if hash == plumbing.ZeroHash { |
| 781 | return fmt.Errorf("checkout remote default: remote ref %s not found", remoteRefName.String()) |
| 782 | } |
| 783 | if err := worktree.Checkout(&git.CheckoutOptions{Branch: branchRefName, Create: true, Hash: hash}); err != nil { |
| 784 | return fmt.Errorf("checkout create branch %s: %w", branchRefName.String(), err) |
| 785 | } |
| 786 | cfg, err := repo.Config() |
| 787 | if err != nil { |
| 788 | return fmt.Errorf("git token store: repo config: %w", err) |
| 789 | } |
| 790 | if _, ok := cfg.Branches[branchShort]; !ok { |
| 791 | cfg.Branches[branchShort] = &config.Branch{Name: branchShort} |
| 792 | } |
| 793 | cfg.Branches[branchShort].Remote = "origin" |
| 794 | cfg.Branches[branchShort].Merge = branchRefName |
| 795 | if err := repo.SetConfig(cfg); err != nil { |
| 796 | return fmt.Errorf("git token store: set branch config: %w", err) |
| 797 | } |
| 798 | return nil |
| 799 | } |
| 800 | |
| 801 | func (s *GitTokenStore) commitAndPushLocked(message string, relPaths ...string) error { |
| 802 | repoDir := s.repoDirSnapshot() |
no test coverage detected