all repos — reposync @ f7aa19dbafcfdd045628a571a02d25bb7848f592

Go program that clones all of my public repos from GitHub to my git server.

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}
20
21func getRepos(username, token string) ([]Repo, error) {
22	url := fmt.Sprintf("https://api.github.com/users/%s/repos", username)
23	req, err := http.NewRequest("GET", url, nil)
24	if err != nil {
25		return nil, err
26	}
27	req.SetBasicAuth(username, token)
28
29	client := &http.Client{}
30	resp, err := client.Do(req)
31	if err != nil {
32		return nil, err
33	}
34	defer resp.Body.Close()
35
36	if resp.StatusCode != http.StatusOK {
37		return nil, fmt.Errorf("failed to fetch repositories: %s", resp.Status)
38	}
39
40	body, err := io.ReadAll(resp.Body)
41	if err != nil {
42		return nil, err
43	}
44
45	var repos []Repo
46	if err := json.Unmarshal(body, &repos); err != nil {
47		return nil, err
48	}
49
50	return repos, nil
51}
52
53func runGitCommand(args ...string) error {
54	cmd := exec.Command("git", args...)
55	cmd.Stdout = os.Stdout
56	cmd.Stderr = os.Stderr
57	return cmd.Run()
58}
59
60func syncRepo(repo Repo, targetDir string) error {
61	repoPath := filepath.Join(targetDir, repo.Name)
62	if _, err := os.Stat(repoPath); os.IsNotExist(err) {
63		fmt.Printf("Cloning repository %s...\n", repo.Name)
64		return runGitCommand("clone", repo.HTMLUrl, repoPath)
65	} else {
66		fmt.Printf("Pulling updates for repository %s...\n", repo.Name)
67		cmd := exec.Command("git", "-C", repoPath, "pull")
68		cmd.Stdout = os.Stdout
69		cmd.Stderr = os.Stderr
70		return cmd.Run()
71	}
72}
73
74func main() {
75	err := godotenv.Load()
76	if err != nil {
77		println("Failed to load .env file: %v\n", err)
78	}
79
80	ghUser := os.Getenv("GITHUB_USERNAME")
81	ghToken := os.Getenv("GITHUB_TOKEN")
82	repoDir := os.Getenv("REPO_DIR")
83
84	if ghUser == "" || ghToken == "" || repoDir == "" {
85		log.Fatalf("GitHub username and token must be provided\n")
86	}
87
88	repos, err := getRepos(ghUser, ghToken)
89	if err != nil {
90		log.Fatalf("Failed to fetch repositories: %v\n", err)
91	}
92
93	for _, repo := range repos {
94		if err := syncRepo(repo, repoDir); err != nil {
95			log.Printf("Failed to sync repository %s: %v\n", repo.Name, err)
96		}
97	}
98}