github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/internal/ghrepo/repo.go (about)

     1  package ghrepo
     2  
     3  import (
     4  	"fmt"
     5  	"net/url"
     6  	"strings"
     7  
     8  	"github.com/ungtb10d/cli/v2/internal/ghinstance"
     9  	ghAuth "github.com/cli/go-gh/pkg/auth"
    10  	"github.com/cli/go-gh/pkg/repository"
    11  )
    12  
    13  // Interface describes an object that represents a GitHub repository
    14  type Interface interface {
    15  	RepoName() string
    16  	RepoOwner() string
    17  	RepoHost() string
    18  }
    19  
    20  // New instantiates a GitHub repository from owner and name arguments
    21  func New(owner, repo string) Interface {
    22  	return NewWithHost(owner, repo, ghinstance.Default())
    23  }
    24  
    25  // NewWithHost is like New with an explicit host name
    26  func NewWithHost(owner, repo, hostname string) Interface {
    27  	return &ghRepo{
    28  		owner:    owner,
    29  		name:     repo,
    30  		hostname: normalizeHostname(hostname),
    31  	}
    32  }
    33  
    34  // FullName serializes a GitHub repository into an "OWNER/REPO" string
    35  func FullName(r Interface) string {
    36  	return fmt.Sprintf("%s/%s", r.RepoOwner(), r.RepoName())
    37  }
    38  
    39  func defaultHost() string {
    40  	host, _ := ghAuth.DefaultHost()
    41  	return host
    42  }
    43  
    44  // FromFullName extracts the GitHub repository information from the following
    45  // formats: "OWNER/REPO", "HOST/OWNER/REPO", and a full URL.
    46  func FromFullName(nwo string) (Interface, error) {
    47  	return FromFullNameWithHost(nwo, defaultHost())
    48  }
    49  
    50  // FromFullNameWithHost is like FromFullName that defaults to a specific host for values that don't
    51  // explicitly include a hostname.
    52  func FromFullNameWithHost(nwo, fallbackHost string) (Interface, error) {
    53  	repo, err := repository.ParseWithHost(nwo, fallbackHost)
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  	return NewWithHost(repo.Owner(), repo.Name(), repo.Host()), nil
    58  }
    59  
    60  // FromURL extracts the GitHub repository information from a git remote URL
    61  func FromURL(u *url.URL) (Interface, error) {
    62  	if u.Hostname() == "" {
    63  		return nil, fmt.Errorf("no hostname detected")
    64  	}
    65  
    66  	parts := strings.SplitN(strings.Trim(u.Path, "/"), "/", 3)
    67  	if len(parts) != 2 {
    68  		return nil, fmt.Errorf("invalid path: %s", u.Path)
    69  	}
    70  
    71  	return NewWithHost(parts[0], strings.TrimSuffix(parts[1], ".git"), u.Hostname()), nil
    72  }
    73  
    74  func normalizeHostname(h string) string {
    75  	return strings.ToLower(strings.TrimPrefix(h, "www."))
    76  }
    77  
    78  // IsSame compares two GitHub repositories
    79  func IsSame(a, b Interface) bool {
    80  	return strings.EqualFold(a.RepoOwner(), b.RepoOwner()) &&
    81  		strings.EqualFold(a.RepoName(), b.RepoName()) &&
    82  		normalizeHostname(a.RepoHost()) == normalizeHostname(b.RepoHost())
    83  }
    84  
    85  func GenerateRepoURL(repo Interface, p string, args ...interface{}) string {
    86  	baseURL := fmt.Sprintf("%s%s/%s", ghinstance.HostPrefix(repo.RepoHost()), repo.RepoOwner(), repo.RepoName())
    87  	if p != "" {
    88  		if path := fmt.Sprintf(p, args...); path != "" {
    89  			return baseURL + "/" + path
    90  		}
    91  	}
    92  	return baseURL
    93  }
    94  
    95  // TODO there is a parallel implementation for non-isolated commands
    96  func FormatRemoteURL(repo Interface, protocol string) string {
    97  	if protocol == "ssh" {
    98  		return fmt.Sprintf("git@%s:%s/%s.git", repo.RepoHost(), repo.RepoOwner(), repo.RepoName())
    99  	}
   100  
   101  	return fmt.Sprintf("%s%s/%s.git", ghinstance.HostPrefix(repo.RepoHost()), repo.RepoOwner(), repo.RepoName())
   102  }
   103  
   104  type ghRepo struct {
   105  	owner    string
   106  	name     string
   107  	hostname string
   108  }
   109  
   110  func (r ghRepo) RepoOwner() string {
   111  	return r.owner
   112  }
   113  
   114  func (r ghRepo) RepoName() string {
   115  	return r.name
   116  }
   117  
   118  func (r ghRepo) RepoHost() string {
   119  	return r.hostname
   120  }