package spitfire import ( "crypto/sha1" "fmt" "io" "log" "os" "strings" "time" ) // Package the APPINDEX update process func PackageAPPINDEX(name, release, version, arch, size, installedSize, description, url, license, origin, maintainer, dependencies, platform string) error { // Mock package file name pkgFile := fmt.Sprintf("%s-%s", name, version) // Calculate checksums checksum := calcChecksum(pkgFile) contentChecksum := calcChecksum(pkgFile) // Timestamp timestamp := time.Now().Unix() // Remove existing entry based on P, R, A, and o fields removeExistingEntry(name, release, arch, origin) // Open or create the APPINDEX file for appending file, err := os.OpenFile("./APPINDEX", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.Fatalf("Failed to open APPINDEX file: %v", err) } defer file.Close() // Write the new entry entry := fmt.Sprintf(` C:%s P:%s R:%s V:%s A:%s S:%s I:%s T:%s U:%s L:%s o:%s m:%s t:%d c:%s D:%s p:%s q: Z:%s `, checksum, name, release, version, arch, size, installedSize, description, url, license, origin, maintainer, timestamp, contentChecksum, dependencies, platform, checksum) if _, err := file.WriteString(entry); err != nil { log.Fatalf("Failed to write to APPINDEX file: %v", err) } fmt.Println("APPINDEX has been updated successfully.") return nil } // calcChecksum calculates a checksum (SHA-1) for a given input string func calcChecksum(input string) string { h := sha1.New() _, _ = io.WriteString(h, input) return fmt.Sprintf("%x", h.Sum(nil)) } // removeExistingEntry removes an existing entry from APPINDEX based on P, R, A, and o fields func removeExistingEntry(name, release, arch, origin string) { // Read file contents content, err := os.ReadFile("./APPINDEX") if err != nil { if os.IsNotExist(err) { return // If file does not exist, no need to remove anything } log.Fatalf("Failed to read APPINDEX: %v", err) } // Remove lines matching the package with the same P, R, A, and o fields lines := strings.Split(string(content), "\n") var newLines []string remove := false for _, line := range lines { // Detect start of an entry by matching on P, R, A, and o if strings.HasPrefix(line, "P:"+name) { remove = true } if remove && strings.HasPrefix(line, "R:"+release) { remove = true } if remove && strings.HasPrefix(line, "A:"+arch) { remove = true } if remove && strings.HasPrefix(line, "o:"+origin) { remove = true } // Stop removal at the end of an entry if remove && line == "" { remove = false continue // Skip the line } // Append lines that are not part of the matching entry if !remove { newLines = append(newLines, line) } } // Write the updated contents back to the file err = os.WriteFile("./APPINDEX", []byte(strings.Join(newLines, "\n")), 0644) if err != nil { log.Fatalf("Failed to update APPINDEX: %v", err) } } // CleanAppIndex cleans up any orphaned "C:" entries and collapses excessive newlines func CleanAppIndex() error { // Read file contents content, err := os.ReadFile("./APPINDEX") if err != nil { return fmt.Errorf("failed to read APPINDEX: %v", err) } // Split the file content into lines lines := strings.Split(string(content), "\n") var newLines []string var currentEntry []string inEntry := false for _, line := range lines { line = strings.TrimSpace(line) // Start of an entry when we encounter a checksum if strings.HasPrefix(line, "C:") { // If we already have a valid entry, add it to newLines if inEntry && len(currentEntry) > 1 { newLines = append(newLines, currentEntry...) } currentEntry = []string{line} inEntry = true } else if inEntry && line == "" { // End of an entry if len(currentEntry) > 1 { newLines = append(newLines, currentEntry...) newLines = append(newLines, "") // Add a blank line to separate entries } currentEntry = nil inEntry = false } else if inEntry { // Continue adding lines to the current entry currentEntry = append(currentEntry, line) } else if line != "" { // Add non-entry lines (for extra safety) newLines = append(newLines, line) } } // In case the last entry was valid if inEntry && len(currentEntry) > 1 { newLines = append(newLines, currentEntry...) } // Collapse consecutive blank lines cleanedContent := strings.Join(newLines, "\n") cleanedContent = strings.ReplaceAll(cleanedContent, "\n\n\n", "\n\n") // Write the cleaned content back to the file err = os.WriteFile("./APPINDEX", []byte(cleanedContent), 0644) if err != nil { return fmt.Errorf("failed to write cleaned APPINDEX: %v", err) } fmt.Println("APPINDEX cleaned successfully.") return nil }