package main import ( "fmt" "log" "os" "path/filepath" "strings" ) // --- Configuration --- // !!! IMPORTANT: Set your GPG Key ID here! // Find it with: gpg --list-secret-keys --keyid-format=long const gpgKeyID = "5D7C9BE47836D2FA48F83C2B4A854AEAF7E0E16D" const dist = "sid" const component = "main" const poolDir = "pool" const distsDir = "dists" var architectures = []string{"amd64", "riscv64", "arm64", "all"} // DebInfo holds the control information for a single .deb package. type DebInfo struct { ControlData map[string]string Filename string Size int64 MD5Sum string SHA1Sum string SHA256Sum string } func main() { log.Println("--- Starting Debian repository generation in Go ---") if gpgKeyID == "YOUR_GPG_KEY_ID" || gpgKeyID == "" { log.Fatal("ERROR: Please set the 'gpgKeyID' constant at the top of the script.") } // 1. Clean and create directory structure distPath := filepath.Join(distsDir, dist) log.Printf("Cleaning up old dists directory: %s", distPath) if err := os.RemoveAll(distPath); err != nil { log.Fatalf("Failed to remove old dists directory: %v", err) } log.Println("Creating new directory structure...") for _, arch := range architectures { binPath := filepath.Join(distPath, component, "binary-"+arch) if err := os.MkdirAll(binPath, 0755); err != nil { log.Fatalf("Failed to create directory %s: %v", binPath, err) } } // 2. Scan pool directory for .deb files and gather info log.Printf("Scanning for .deb files in %s/ જુ", poolDir) debInfos, err := scanDebs(poolDir) if err != nil { log.Fatalf("Failed to scan .deb files: %v", err) } log.Printf("Found %d total .deb packages.", len(debInfos)) // 3. Group packages by architecture debsByArch := make(map[string][]DebInfo) for _, deb := range debInfos { arch := deb.ControlData["Architecture"] debsByArch[arch] = append(debsByArch[arch], deb) } // Add the 'all' packages to each specific architecture list as well, as is standard. for _, arch := range architectures { if arch != "all" { debsByArch[arch] = append(debsByArch[arch], debsByArch["all"]...) } } // 4. Generate Packages files log.Println("Generating Packages files...") for _, arch := range architectures { binPath := filepath.Join(distPath, component, "binary-"+arch) packagesFile := filepath.Join(binPath, "Packages") var content strings.Builder for _, deb := range debsByArch[arch] { for key, val := range deb.ControlData { fmt.Fprintf(&content, "%s: %s\n", key, val) } fmt.Fprintf(&content, "Filename: %s\n", deb.Filename) fmt.Fprintf(&content, "Size: %d\n", deb.Size) fmt.Fprintf(&content, "MD5sum: %s\n", deb.MD5Sum) fmt.Fprintf(&content, "SHA1: %s\n", deb.SHA1Sum) fmt.Fprintf(&content, "SHA256: %s\n", deb.SHA256Sum) fmt.Fprintln(&content) } if err := os.WriteFile(packagesFile, []byte(content.String()), 0644); err != nil { log.Fatalf("Failed to write Packages file for %s: %v", arch, err) } // Compress the Packages file if err := compressFile(packagesFile, "gz"); err != nil { log.Fatalf("Failed to gzip Packages file for %s: %v", arch, err) } if err := compressFile(packagesFile, "bz2"); err != nil { log.Fatalf("Failed to bzip2 Packages file for %s: %v", arch, err) } } // 5. Generate and sign the Release file log.Println("Generating and signing Release file...") if err := generateAndSignReleaseFile(distPath); err != nil { log.Fatalf("Failed to generate or sign Release file: %v", err) } log.Println("--- Repository generation complete! ---") }