package main import ( "errors" "fmt" "log" "os" "os/exec" "path/filepath" "strconv" "strings" ) func main() { token := os.Getenv("TOKEN") if token == "" { log.Fatalf("TOKEN environment variable not set") } client := GiteaClient{ BaseURL: "https://gitea.seeseepuff.be", Token: token, } org := "archlinux" workDir := "./work/" err := os.RemoveAll(workDir) if err != nil { log.Fatalf("failed to remove %s: %v", workDir, err) } err = os.MkdirAll(workDir, os.ModePerm) if err != nil { log.Fatalf("failed to create %s: %v", workDir, err) } repos, err := client.getRepositories(org) if err != nil { log.Fatalf("Failed to get repositories: %v", err) } failedRepos := make([]string, 0) for _, repo := range repos { if repo.Template || strings.Contains(repo.Name, "skip-autobuild") { // Skip template repositories continue } wasRepoProcessed := processRepo(&client, workDir, repo) if !wasRepoProcessed { failedRepos = append(failedRepos, repo.Name) } } if len(failedRepos) > 0 { log.Println("The following repos failed to process:") for _, repo := range failedRepos { log.Printf(" - %s", repo) } os.Exit(1) } } func processRepo(client *GiteaClient, workDir string, repo Repository) (success bool) { log.Printf("Checking %s", repo.FullName) hasFile, err := client.hasPKGBUILD(repo) if err != nil { log.Printf("Error checking for PKGBUILD: %v", err) return false } if !hasFile { log.Println("PKGBUILD not found, skipping") return true } repoPath, err := cloneRepository(client.Token, repo, workDir) if err != nil { log.Printf("Error cloning repository: %v", err) return false } // Run pre-run script (if it exists) requirePush := false defer func() { if requirePush { err = pushRepository(repoPath) if err != nil { log.Printf("Error pushing repository: %v", err) success = false } } }() preRunScript := filepath.Join(repoPath, "prerun.sh") if _, err := os.Stat(preRunScript); !os.IsNotExist(err) { cmd := exec.Command("/bin/sh", "./prerun.sh") cmd.Dir = repoPath cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err = cmd.Run() if err != nil { log.Printf("Error running pre-run script: %v", err) return false } requirePush = true } // Check if the repository is up-to-date upToDate, err := checkUpToDate(repoPath) if err != nil { log.Printf("Error checking if up to date: %v", err) return false } if upToDate { log.Printf("%s is up-to-date, skipping", repo.FullName) return true } log.Printf("%s requires bumping, running script", repo.FullName) updated, err := bumpRepository(repoPath) if err != nil { log.Printf("Error bumping repository: %v", err) return false } if updated { requirePush = true } return true } func cloneRepository(token string, repo Repository, workDir string) (string, error) { targetPath := filepath.Join(workDir, repo.Name) cmd := exec.Command("git", "clone", fmt.Sprintf("https://seeseemelk:%s@gitea.seeseepuff.be/archlinux/%s", token, repo.Name), targetPath) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err := cmd.Run() if err != nil { return "", fmt.Errorf("failed to clone %s: %w", repo.Name, err) } return targetPath, nil } func checkUpToDate(repoPath string) (bool, error) { log.Println("Checking if up-to-date") cmd := exec.Command("bash", "./check-up-to-date.sh", repoPath) output, err := cmd.CombinedOutput() log.Println("Command output: ", string(output)) if err != nil { return false, fmt.Errorf("failed to inspect %s: %w", repoPath, err) } if strings.Index(string(output), "UP-TO-DATE") >= 0 { return true, nil } else if strings.Index(string(output), "OUT-OF-DATE") >= 0 { return false, nil } return false, errors.New("error parsing command output") } /* Finds the line that says "pkgrel=NUMBER" in the repository's PKGBUILD file, and increments the number by 1. */ func bumpRepository(repoPath string) (bool, error) { pkgbuildPath := filepath.Join(repoPath, "PKGBUILD") // Read the file content, err := os.ReadFile(pkgbuildPath) if err != nil { log.Fatalf("failed to read %s: %v", pkgbuildPath, err) } lines := strings.Split(string(content), "\n") updated := false // Iterate through lines to find and update pkgrel for i, line := range lines { if strings.HasPrefix(line, "pkgrel=") { parts := strings.SplitN(line, "=", 2) if len(parts) == 2 { // Parse and increment the pkgrel value pkgrel, err := strconv.Atoi(strings.TrimSpace(parts[1])) if err != nil { log.Fatalf("Failed to parse pkgrel value: %v", err) } lines[i] = fmt.Sprintf("pkgrel=%d", pkgrel+1) updated = true break } } } if !updated { return false, fmt.Errorf("pkgrel line not found in PKGBUILD file") } // Write the updated content back to the PKGBUILD file err = os.WriteFile(pkgbuildPath, []byte(strings.Join(lines, "\n")), 0644) if err != nil { return false, fmt.Errorf("error writing updated PKGBUILD file: %w", err) } log.Println("PKGBUILD updated, creating commit") // Create commit cmd := exec.Command("git", "commit", "PKGBUILD", "-m", "Bump pkgrel") cmd.Dir = repoPath cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err = cmd.Run() if err != nil { return false, fmt.Errorf("failed to commit changes: %w", err) } return true, nil } func pushRepository(repoPath string) error { // Push commit log.Println("Pushing commit") cmd := exec.Command("git", "push") cmd.Dir = repoPath cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err := cmd.Run() if err != nil { return fmt.Errorf("failed to push changes: %w", err) } log.Println("Successfully bumped pkgrel in PKGBUILD") return nil }