Loading

Paste #p99xhz9rh

  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 admin API token")
  16.     doDelete := flag.Bool("delete", false, "Actually delete empty repos (default is dry-run)")
  17.     pageSize := flag.Int("page-size", 50, "Repos 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.     client.SetContext(context.Background())
  33.  
  34.     var emptyRepos []*gitea.Repository
  35.     page := 1
  36.  
  37.     for {
  38.         repos, resp, err := client.AdminListRepos(gitea.ListReposOptions{
  39.             ListOptions: gitea.ListOptions{
  40.                 Page:     page,
  41.                 PageSize: *pageSize,
  42.             },
  43.         })
  44.         if err != nil {
  45.             log.Fatalf("AdminListRepos failed on page %d: %v", page, err)
  46.         }
  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 := "<unknown>"
  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("\n🧪 Dry run only. Re-run with -delete to actually delete these repos.")
  80.         return
  81.     }
  82.  
  83.     fmt.Println("\n🔥 Deleting empty repositories...")
  84.  
  85.     for _, r := range emptyRepos {
  86.         if r.Owner == nil {
  87.             fmt.Printf("Skipping %s (ID=%d): missing owner\n", r.Name, r.ID)
  88.             continue
  89.         }
  90.  
  91.         owner := r.Owner.UserName
  92.         fmt.Printf("Deleting %s/%s ... ", owner, r.Name)
  93.  
  94.         if _, err := client.DeleteRepo(owner, r.Name); err != nil {
  95.             fmt.Printf("ERROR: %v\n", err)
  96.             continue
  97.         }
  98.  
  99.         fmt.Println("OK")
  100.     }
  101.  
  102.     fmt.Println("✅ Done.")
  103. }

Comments