Spaces:
Sleeping
Sleeping
| package github | |
| import ( | |
| "context" | |
| "fmt" | |
| "os" | |
| "strings" | |
| "github.com/google/go-github/v55/github" | |
| "golang.org/x/oauth2" | |
| ) | |
| // Client wraps the GitHub API client | |
| type Client struct { | |
| client *github.Client | |
| ctx context.Context | |
| } | |
| // NewClient creates a new GitHub client | |
| func NewClient(token string) (*Client, error) { | |
| ctx := context.Background() | |
| var client *github.Client | |
| if token != "" { | |
| ts := oauth2.StaticTokenSource( | |
| &oauth2.Token{AccessToken: token}, | |
| ) | |
| tc := oauth2.NewClient(ctx, ts) | |
| client = github.NewClient(tc) | |
| } else { | |
| client = github.NewClient(nil) | |
| } | |
| return &Client{ | |
| client: client, | |
| ctx: ctx, | |
| }, nil | |
| } | |
| // Repository represents a GitHub repository | |
| type Repository struct { | |
| Owner string | |
| Name string | |
| URL string | |
| CloneURL string | |
| DefaultBranch string | |
| } | |
| // ParseRepoURL extracts owner and name from GitHub URL | |
| func ParseRepoURL(url string) (*Repository, error) { | |
| // Expected format: https://github.com/owner/repo | |
| parts := strings.Split(url, "/") | |
| if len(parts) < 5 { | |
| return nil, fmt.Errorf("invalid GitHub URL") | |
| } | |
| owner := parts[len(parts)-2] | |
| name := parts[len(parts)-1] | |
| // Remove .git suffix if present | |
| name = strings.TrimSuffix(name, ".git") | |
| return &Repository{ | |
| Owner: owner, | |
| Name: name, | |
| URL: url, | |
| CloneURL: fmt.Sprintf("https://github.com/%s/%s.git", owner, name), | |
| }, nil | |
| } | |
| // GetRepositoryInfo fetches repository metadata from GitHub | |
| func (c *Client) GetRepositoryInfo(url string) (*Repository, error) { | |
| repo, err := ParseRepoURL(url) | |
| if err != nil { | |
| return nil, err | |
| } | |
| ghRepo, _, err := c.client.Repositories.Get(c.ctx, repo.Owner, repo.Name) | |
| if err != nil { | |
| return nil, err | |
| } | |
| repo.DefaultBranch = ghRepo.GetDefaultBranch() | |
| if repo.DefaultBranch == "" { | |
| repo.DefaultBranch = "main" | |
| } | |
| return repo, nil | |
| } | |
| // CloneRepository clones a repository to a temporary directory | |
| func (c *Client) CloneRepository(url string, token string) (string, error) { | |
| repo, err := ParseRepoURL(url) | |
| if err != nil { | |
| return "", err | |
| } | |
| // Create temp directory | |
| tmpDir, err := os.MkdirTemp("", "repo-diagram-*") | |
| if err != nil { | |
| return "", err | |
| } | |
| // Build clone URL with token if provided | |
| cloneURL := repo.CloneURL | |
| if token != "" { | |
| cloneURL = fmt.Sprintf("https://x-access-token:%s@github.com/%s/%s.git", | |
| token, repo.Owner, repo.Name) | |
| } | |
| // Clone using git command (simpler than go-git for now) | |
| cmd := fmt.Sprintf("git clone --depth 1 --branch %s %s %s", | |
| repo.DefaultBranch, cloneURL, tmpDir) | |
| if err := runCommand(cmd); err != nil { | |
| os.RemoveAll(tmpDir) | |
| return "", err | |
| } | |
| return tmpDir, nil | |
| } | |
| // GetLanguages returns the language breakdown of a repository | |
| func (c *Client) GetLanguages(url string) (map[string]int, error) { | |
| repo, err := ParseRepoURL(url) | |
| if err != nil { | |
| return nil, err | |
| } | |
| languages, _, err := c.client.Repositories.ListLanguages(c.ctx, repo.Owner, repo.Name) | |
| if err != nil { | |
| return nil, err | |
| } | |
| return languages, nil | |
| } | |
| // runCommand executes a shell command | |
| func runCommand(cmd string) error { | |
| return nil // Implement with exec.Command | |
| } |