github.com/harryzcy/snuuze@v0.3.3-0.20240314015559-83a8fc5627a8/platform/common.go (about)

     1  package platform
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"strings"
     7  
     8  	"github.com/harryzcy/snuuze/config"
     9  	"github.com/harryzcy/snuuze/types"
    10  )
    11  
    12  var (
    13  	ErrUnimplemented      = errors.New("not implemented")
    14  	ErrInvalidGitPlatform = errors.New("unsupported git platform")
    15  	ErrInvalidGitURL      = errors.New("invalid git url")
    16  	ErrInvalidServerURL   = errors.New("invalid server URL")
    17  	ErrNoInsecureServer   = errors.New("insecure server is not supported")
    18  	ErrServerRequired     = errors.New("server is required")
    19  )
    20  
    21  type Client interface {
    22  	Token(ctx context.Context) (string, error)
    23  
    24  	ListRepos() ([]Repo, error)
    25  	// ListTags returns a sorted list of tags for the given repo
    26  	ListTags(params *ListTagsInput) ([]string, error)
    27  
    28  	CreatePullRequest(input *CreatePullRequestInput) error
    29  }
    30  
    31  type GitPlatform int
    32  
    33  const (
    34  	GitPlatformUnknown GitPlatform = iota
    35  	GitPlatformGitHub
    36  	GitPlatformGitea
    37  )
    38  
    39  type NewClientOptions struct {
    40  	Platform GitPlatform
    41  	URL      string
    42  }
    43  
    44  // NewClient returns a new Client based on Git URL
    45  func NewClient(options NewClientOptions) (Client, error) {
    46  	platform := options.Platform
    47  	var host string
    48  	if platform == GitPlatformUnknown || platform == GitPlatformGitea {
    49  		platform, host = DetermineGitPlatform(options.URL)
    50  	}
    51  
    52  	switch platform {
    53  	case GitPlatformGitHub:
    54  		return NewGitHubClient()
    55  	case GitPlatformGitea:
    56  		return NewGiteaClient(host), nil
    57  	}
    58  
    59  	return nil, ErrInvalidGitPlatform
    60  }
    61  
    62  var getGiteaConfigs = func() []types.GiteaConfig {
    63  	return config.GetHostingConfig().Gitea
    64  }
    65  
    66  // DetermineGitPlatform returns the GitPlatform and the host of the given git URL
    67  func DetermineGitPlatform(gitURL string) (GitPlatform, string) {
    68  	urlInfo, err := parseURL(gitURL)
    69  	if err != nil {
    70  		return GitPlatformUnknown, ""
    71  	}
    72  
    73  	if urlInfo.host == "github.com" {
    74  		return GitPlatformGitHub, "https://github.com"
    75  	}
    76  
    77  	for _, giteaConfig := range getGiteaConfigs() {
    78  		configuredHost := giteaConfig.GetHost()
    79  		configuredInfo, err := parseURL(configuredHost)
    80  		if err != nil {
    81  			continue
    82  		}
    83  
    84  		if urlInfo.host == configuredInfo.host {
    85  			return GitPlatformGitea, configuredHost
    86  		}
    87  	}
    88  
    89  	return GitPlatformUnknown, ""
    90  }
    91  
    92  type hostInfo struct {
    93  	protocol string
    94  	host     string
    95  }
    96  
    97  func parseURL(url string) (*hostInfo, error) {
    98  	for _, protocol := range []string{"https", "http"} {
    99  		prefix := protocol + "://"
   100  		if strings.HasPrefix(url, prefix) {
   101  			url = strings.TrimPrefix(url, prefix)
   102  			url = strings.SplitN(url, "/", 2)[0]
   103  			return &hostInfo{
   104  				protocol: protocol,
   105  				host:     url,
   106  			}, nil
   107  		}
   108  	}
   109  
   110  	if strings.HasPrefix(url, "git@") {
   111  		url = strings.TrimPrefix(url, "git@")
   112  		url = strings.SplitN(url, ":", 2)[0]
   113  		return &hostInfo{
   114  			protocol: "ssh",
   115  			host:     url,
   116  		}, nil
   117  	}
   118  
   119  	return nil, ErrInvalidGitURL
   120  }
   121  
   122  type Repo struct {
   123  	Server        string `json:"server"`
   124  	Owner         string `json:"owner"`
   125  	Repo          string `json:"repo"`
   126  	URL           string `json:"url"`
   127  	IsPrivate     bool   `json:"isPrivate"`
   128  	DefaultBranch string `json:"defaultBranch"`
   129  }
   130  
   131  type ListTagsInput struct {
   132  	Owner  string
   133  	Repo   string
   134  	Prefix string // optional
   135  }
   136  
   137  type CreatePullRequestInput struct {
   138  	Title string
   139  	Body  string
   140  	Base  string
   141  	Head  string
   142  	Owner string
   143  	Repo  string
   144  }