Loading

gitea-script

  1. package main
  2.  
  3. import (
  4.     "context"
  5.     "flag"
  6.     "fmt"
  7.     "log"
  8.     "os"
  9.  
  10.     "code.gitea.io/sdk/gitea"
  11. )
  12.  
  13. func main() {
  14.     baseURL := flag.String("base-url", os.Getenv("GITEA_BASE_URL"), "Gitea base URL, e.g. https://gitea.example.com")
  15.     token := flag.String("token", os.Getenv("GITEA_TOKEN"), "Gitea API token")
  16.     doDelete := flag.Bool("delete", false, "Actually delete empty repos (default is dry-run)")
  17.     pageSize := flag.Int("page-size", 50, "Number of repos to fetch per page")
  18.     flag.Parse()
  19.  
  20.     if *baseURL == "" {
  21.         log.Fatal("base URL must be provided via -base-url or GITEA_BASE_URL")
  22.     }
  23.     if *token == "" {
  24.         log.Fatal("token must be provided via -token or GITEA_TOKEN")
  25.     }
  26.  
  27.     client, err := gitea.NewClient(*baseURL, gitea.SetToken(*token))
  28.     if err != nil {
  29.         log.Fatalf("failed to create Gitea client: %v", err)
  30.     }
  31.  
  32.     // Optional: set a context (useful if you want timeouts/cancellation)
  33.     client.SetContext(context.Background())
  34.  
  35.     var emptyRepos []*gitea.Repository
  36.     page := 1
  37.  
  38.     for {
  39.         repos, resp, err := client.ListMyRepos(gitea.ListReposOptions{
  40.             ListOptions: gitea.ListOptions{
  41.                 Page:     page,
  42.                 PageSize: *pageSize,
  43.             },
  44.         })
  45.         if err != nil {
  46.             log.Fatalf("failed to list repos (page %d): %v", page, err)
  47.         }
  48.         if len(repos) == 0 {
  49.             break
  50.         }
  51.  
  52.         for _, r := range repos {
  53.             if r.Empty {
  54.                 emptyRepos = append(emptyRepos, r)
  55.             }
  56.         }
  57.  
  58.         if resp == nil || resp.NextPage == 0 {
  59.             break
  60.         }
  61.         page = resp.NextPage
  62.     }
  63.  
  64.     if len(emptyRepos) == 0 {
  65.         fmt.Println("No empty repositories found.")
  66.         return
  67.     }
  68.  
  69.     fmt.Printf("Found %d empty repositories:\n", len(emptyRepos))
  70.     for _, r := range emptyRepos {
  71.         owner := ""
  72.         if r.Owner != nil {
  73.             owner = r.Owner.UserName
  74.         }
  75.         fmt.Printf("- %s/%s (ID=%d)\n", owner, r.Name, r.ID)
  76.     }
  77.  
  78.     if !*doDelete {
  79.         fmt.Println("\nDry run only. Re-run with -delete to actually delete these repos.")
  80.         return
  81.     }
  82.  
  83.     fmt.Println("\nDeleting empty repositories...")
  84.     for _, r := range emptyRepos {
  85.         if r.Owner == nil {
  86.             fmt.Printf("Skipping repo ID=%d (%s): missing owner info\n", r.ID, r.Name)
  87.             continue
  88.         }
  89.         owner := r.Owner.UserName
  90.         fmt.Printf("Deleting %s/%s... ", owner, r.Name)
  91.  
  92.         if _, err := client.DeleteRepo(owner, r.Name); err != nil {
  93.             fmt.Printf("ERROR: %v\n", err)
  94.             continue
  95.         }
  96.         fmt.Println("OK")
  97.     }
  98.  
  99.     fmt.Println("Done.")
  100. }

Comments