Builder/spitfire/appindex.go

182 lines
4.6 KiB
Go
Raw Normal View History

2024-09-08 23:25:07 +00:00
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
}