182 lines
4.6 KiB
Go
182 lines
4.6 KiB
Go
|
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
|
||
|
}
|