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("Fetching updates for bare repository %s...\n", repo.Name)
75 cmd := exec.Command("git", "--git-dir", repoPath, "fetch", "--all")
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 err := writeDescription(repoPath, repo.Description); err != nil {
85 return fmt.Errorf("failed to write description for %s: %v", repo.Name, err)
86 }
87
88 return nil
89}
90
91func main() {
92 err := godotenv.Load()
93 if err != nil {
94 println("Failed to load .env file: %v\n", err)
95 }
96
97 ghUser := os.Getenv("GITHUB_USERNAME")
98 ghToken := os.Getenv("GITHUB_TOKEN")
99 repoDir := os.Getenv("REPO_DIR")
100
101 if ghUser == "" || ghToken == "" || repoDir == "" {
102 log.Fatalf("GitHub username and token must be provided\n")
103 }
104
105 repos, err := getRepos(ghUser, ghToken)
106 if err != nil {
107 log.Fatalf("Failed to fetch repositories: %v\n", err)
108 }
109
110 for _, repo := range repos {
111 if err := syncRepo(repo, repoDir); err != nil {
112 log.Printf("Failed to sync repository %s: %v\n", repo.Name, err)
113 }
114 }
115}