main.go (view raw)
1package main
2
3import (
4 "encoding/json"
5 "fmt"
6 "io"
7 "log"
8 "net/http"
9 "os"
10 "os/exec"
11 "path/filepath"
12
13 "github.com/joho/godotenv"
14)
15
16type Repo struct {
17 Name string `json:"name"`
18 HTMLUrl string `json:"html_url"`
19 Description string `json:"description"`
20}
21
22func getRepos(username, token string) ([]Repo, error) {
23 url := fmt.Sprintf("https://api.github.com/users/%s/repos", username)
24 req, err := http.NewRequest("GET", url, nil)
25 if err != nil {
26 return nil, err
27 }
28 req.SetBasicAuth(username, token)
29
30 client := &http.Client{}
31 resp, err := client.Do(req)
32 if err != nil {
33 return nil, err
34 }
35 defer resp.Body.Close()
36
37 if resp.StatusCode != http.StatusOK {
38 return nil, fmt.Errorf("failed to fetch repositories: %s", resp.Status)
39 }
40
41 body, err := io.ReadAll(resp.Body)
42 if err != nil {
43 return nil, err
44 }
45
46 var repos []Repo
47 if err := json.Unmarshal(body, &repos); err != nil {
48 return nil, err
49 }
50
51 return repos, nil
52}
53
54func runGitCommand(args ...string) error {
55 cmd := exec.Command("git", args...)
56 cmd.Stdout = os.Stdout
57 cmd.Stderr = os.Stderr
58 return cmd.Run()
59}
60
61func writeDescription(repoPath, description string) error {
62 descriptionPath := filepath.Join(repoPath, "description")
63 return os.WriteFile(descriptionPath, []byte(description), 0644)
64}
65
66func syncRepo(repo Repo, targetDir string) error {
67 repoPath := filepath.Join(targetDir, repo.Name+".git")
68 if _, err := os.Stat(repoPath); os.IsNotExist(err) {
69 fmt.Printf("Cloning repository %s as bare...\n", repo.Name)
70 if err := runGitCommand("clone", "--bare", repo.HTMLUrl, repoPath); err != nil {
71 return err
72 }
73 } else {
74 fmt.Printf("Pulling updates for repository %s...\n", repo.Name)
75 cmd := exec.Command("git", "-C", repoPath, "pull")
76 cmd.Stdout = os.Stdout
77 cmd.Stderr = os.Stderr
78 if err := cmd.Run(); err != nil {
79 return err
80 }
81 }
82
83 // Write the repository description
84 if repo.Description != "" {
85 if err := writeDescription(repoPath, repo.Description); err != nil {
86 return fmt.Errorf("failed to write description for %s: %v", repo.Name, err)
87 }
88 }
89
90 return nil
91}
92
93func main() {
94 err := godotenv.Load()
95 if err != nil {
96 println("Failed to load .env file: %v\n", err)
97 }
98
99 ghUser := os.Getenv("GITHUB_USERNAME")
100 ghToken := os.Getenv("GITHUB_TOKEN")
101 repoDir := os.Getenv("REPO_DIR")
102
103 if ghUser == "" || ghToken == "" || repoDir == "" {
104 log.Fatalf("GitHub username and token must be provided\n")
105 }
106
107 repos, err := getRepos(ghUser, ghToken)
108 if err != nil {
109 log.Fatalf("Failed to fetch repositories: %v\n", err)
110 }
111
112 for _, repo := range repos {
113 if err := syncRepo(repo, repoDir); err != nil {
114 log.Printf("Failed to sync repository %s: %v\n", repo.Name, err)
115 }
116 }
117}