updated APPINDEX

This commit is contained in:
partisan 2024-12-23 11:24:42 +01:00
parent 3545a5f73b
commit 2bb34d2f5c
3 changed files with 214 additions and 111 deletions

View file

@ -124,24 +124,28 @@ go run . -h
## APPINDEX example: ## APPINDEX example:
``` ```
C:905cd0cc2dea9e400e1ecd099462b6b19188a9f1 C:a6af7ebb5c1382084704be0b5714ab026c819d63
P:Spitfire P:spitfire-browser
R:nightly R:nightly
V:2024.09.08 V:2024.12.23
A:amd64 A:amd64
S:788506622 S:838594187
I:3324483350 I:3595780372
T:Spitfire build T:Spitfire
U:https://spitfirebrowser.xyz/ U:https://spitfirebrowser.xyz/
L:AGPL-3.0 L:AGPL-3.0
o:browser o:browser
m:Internet Addict m:Internet Addict
t:1725830641 t:1734949294
c:905cd0cc2dea9e400e1ecd099462b6b19188a9f1
D: D:
p:linux p:linux
q: q:
Z:905cd0cc2dea9e400e1ecd099462b6b19188a9f1 d:https://downloads.sourceforge.net/project/spitfire-browser/browser/amd64/nightly/2024.12.23/browser-amd64-nightly-linux.tar.gz
I:https://weforge.xyz/Spitfire/Branding/raw/branch/main/active/browser/icon.svg
S:https://spitfirebrowser.xyz/static/images/screenshots/1.png
T:browser,experimental,testing
r: Automated Nightly build of Spitfire
c:a6af7ebb5c1382084704be0b5714ab026c819d63
``` ```
## Repository structure ## Repository structure

124
main.go
View file

@ -39,6 +39,7 @@ var (
url = "https://spitfirebrowser.xyz/" url = "https://spitfirebrowser.xyz/"
licence = "AGPL-3.0" licence = "AGPL-3.0"
name = "Spitfire" name = "Spitfire"
packageName = "spitfire-browser"
maintainer = "Internet Addict" maintainer = "Internet Addict"
initialDir string initialDir string
) )
@ -260,15 +261,20 @@ func PackageAndUploadProcess() {
log.Fatalf("Error: no valid build or upload path provided.") log.Fatalf("Error: no valid build or upload path provided.")
} }
// Calculate and display uncompressed size // Calculate & display uncompressed size
uncompressedSize, err := spitfire.GetDirectorySize(pathToUse) uncompressedSize, err := spitfire.GetDirectorySize(pathToUse)
if err != nil { if err != nil {
log.Fatalf("Failed to calculate uncompressed size: %v", err) log.Fatalf("Failed to calculate uncompressed size: %v", err)
} }
fmt.Printf("Uncompressed directory size: %s\n", spitfire.BytesToHumanReadable(uncompressedSize)) fmt.Printf("Uncompressed directory size: %s\n", spitfire.BytesToHumanReadable(uncompressedSize))
// Compress the build directory // Create the tar.gz name, e.g. "browser-amd64-nightly-linux.tar.gz"
outputCompressedFile := filepath.Join(".", fmt.Sprintf("%s-%s-%s-%s.tar.gz", component, arch, release, platform)) outputCompressedFile := filepath.Join(".", fmt.Sprintf(
"%s-%s-%s-%s.tar.gz",
component, arch, release, platform,
))
// Compress if requested
if compress { if compress {
err := spitfire.CompressDirectory(pathToUse, outputCompressedFile) err := spitfire.CompressDirectory(pathToUse, outputCompressedFile)
if err != nil { if err != nil {
@ -277,61 +283,85 @@ func PackageAndUploadProcess() {
fmt.Printf("Build directory compressed to: %s\n", outputCompressedFile) fmt.Printf("Build directory compressed to: %s\n", outputCompressedFile)
} }
// Calculate and display compressed size // Compressed size
compressedSize, err := spitfire.GetFileSize(outputCompressedFile) compressedSize, err := spitfire.GetFileSize(outputCompressedFile)
if err != nil { if err != nil {
log.Fatalf("Failed to get compressed file size: %v", err) log.Fatalf("Failed to get compressed file size: %v", err)
} }
fmt.Printf("Compressed file size: %s\n", spitfire.BytesToHumanReadable(compressedSize)) fmt.Printf("Compressed file size: %s\n", spitfire.BytesToHumanReadable(compressedSize))
// Calculate and display compression efficiency // Show compression ratio & efficiency
compressionRatio, efficiency := spitfire.CalculateCompressionEfficiency(uncompressedSize, compressedSize) compressionRatio, efficiency := spitfire.CalculateCompressionEfficiency(uncompressedSize, compressedSize)
fmt.Printf("Compression ratio: %.2f:1\n", compressionRatio) fmt.Printf("Compression ratio: %.2f:1\n", compressionRatio)
fmt.Printf("Compression efficiency: %.2f%%\n", efficiency) fmt.Printf("Compression efficiency: %.2f%%\n", efficiency)
// Handle uploading // If not uploading, we're done
if upload { if !upload {
config, err := spitfire.LoadConfig() return
if err != nil {
log.Fatalf("Failed to load SourceForge config: %v", err)
}
if _, err := os.Stat(outputCompressedFile); err == nil {
err = spitfire.Upload(config, outputCompressedFile, "/home/frs/project/spitfire-browser/"+component+"/"+arch+"/"+release+"/"+version+"/")
if err != nil {
log.Fatalf("Failed to upload compressed file: %v", err)
}
fmt.Println("Compressed file uploaded successfully.")
} else {
log.Fatalf("No compressed file found to upload.")
}
err = spitfire.DownloadAPPINDEX(config, "/home/frs/project/spitfire-browser/")
if err != nil {
fmt.Println("Failed to download APPINDEX. A new APPINDEX will be created and uploaded.")
}
err = spitfire.PackageAPPINDEX(
name, release, version, arch,
fmt.Sprintf("%d", compressedSize),
fmt.Sprintf("%d", uncompressedSize),
"Spitfire build", url, licence, component, maintainer, "", platform,
)
if err != nil {
log.Fatalf("Failed to update APPINDEX: %v", err)
}
fmt.Println("APPINDEX updated successfully.")
if err := spitfire.CleanAppIndex(); err != nil {
log.Fatalf("Failed to clean APPINDEX: %v", err)
}
err = spitfire.UploadAPPINDEX(config, "/home/frs/project/spitfire-browser/")
if err != nil {
log.Fatalf("Failed to upload updated APPINDEX: %v", err)
}
fmt.Println("APPINDEX uploaded successfully.")
} }
// Load SourceForge config
config, err := spitfire.LoadConfig()
if err != nil {
log.Fatalf("Failed to load SourceForge config: %v", err)
}
// Check tarball existence
if _, err := os.Stat(outputCompressedFile); err != nil {
log.Fatalf("No compressed file found to upload: %v", err)
}
// The subdirectory path in the SF project
// e.g. "browser/amd64/nightly/2024.12.23"
uploadDir := fmt.Sprintf("%s/%s/%s/%s", component, arch, release, version)
// 1) Upload the file to SourceForge once
err = spitfire.Upload(config, outputCompressedFile,
"/home/frs/project/spitfire-browser/"+uploadDir+"/")
if err != nil {
log.Fatalf("Failed to upload compressed file: %v", err)
}
fmt.Println("Compressed file uploaded successfully.")
// 2) Download existing APPINDEX or create new
err = spitfire.DownloadAPPINDEX(config, "/home/frs/project/spitfire-browser/")
if err != nil {
fmt.Println("Failed to download APPINDEX. A new one will be created and uploaded.")
}
// 3) Update the APPINDEX
err = spitfire.PackageAPPINDEX(
packageName, // e.g. "spitfire-browser"
release, // e.g. "nightly"
version, // e.g. "2024.12.23"
arch,
fmt.Sprintf("%d", compressedSize),
fmt.Sprintf("%d", uncompressedSize),
name, // e.g. "Spitfire"
url,
licence,
component,
maintainer,
"", // dependencies
platform,
uploadDir,
)
if err != nil {
log.Fatalf("Failed to update APPINDEX: %v", err)
}
fmt.Println("APPINDEX updated successfully.")
// 4) Clean
if err := spitfire.CleanAppIndex(); err != nil {
log.Fatalf("Failed to clean APPINDEX: %v", err)
}
// 5) Upload the updated APPINDEX
err = spitfire.UploadAPPINDEX(config, "/home/frs/project/spitfire-browser/")
if err != nil {
log.Fatalf("Failed to upload updated APPINDEX: %v", err)
}
fmt.Println("APPINDEX uploaded successfully.")
} }
// restoreWorkingDirectory restores the initial working directory after any operation that might change it. // restoreWorkingDirectory restores the initial working directory after any operation that might change it.

View file

@ -11,20 +11,38 @@ import (
) )
// Package the APPINDEX update process // Package the APPINDEX update process
func PackageAPPINDEX(name, release, version, arch, size, installedSize, description, url, license, origin, maintainer, dependencies, platform string) error { func PackageAPPINDEX(
// Mock package file name name, // e.g. "spitfire-browser"
pkgFile := fmt.Sprintf("%s-%s", name, version) release, // e.g. "nightly"
version, // e.g. "2024.12.21"
arch, // e.g. "amd64"
size, // e.g. "838205457" (compressed size)
installedSize, // e.g. "3595495684" (uncompressed size)
description, // e.g. "Spitfire build"
url, // e.g. "https://spitfirebrowser.xyz/"
license, // e.g. "AGPL-3.0"
origin, // e.g. "browser"
maintainer, // e.g. "Internet Addict"
dependencies, // usually blank ..."
platform, // e.g. "linux"
remoteDir string, // e.g. "nightly/linux/amd64"
) error {
// Calculate checksums // Construct a filename that matches what you compress & upload
checksum := calcChecksum(pkgFile) // Adjust this naming convention to match your compress step exactly!
contentChecksum := calcChecksum(pkgFile) // Example: "spitfire-browser-nightly-amd64-linux.tar.gz"
fileName := fmt.Sprintf("%s-%s-%s-%s.tar.gz", origin, arch, release, platform)
// Timestamp // If you have a real file on disk, you might call `calcChecksum(fileName)`.
timestamp := time.Now().Unix() // For demo, we call `calcChecksum` with a mock package name.
checksum := calcChecksum(fileName)
// Remove existing entry based on P, R, A, and o fields // Remove existing entry based on P, R, A, o (if you want to deduplicate).
removeExistingEntry(name, release, arch, origin) removeExistingEntry(name, release, arch, origin)
// Use current Unix timestamp
timestamp := time.Now().Unix()
// Open or create the APPINDEX file for appending // Open or create the APPINDEX file for appending
file, err := os.OpenFile("./APPINDEX", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) file, err := os.OpenFile("./APPINDEX", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil { if err != nil {
@ -32,30 +50,42 @@ func PackageAPPINDEX(name, release, version, arch, size, installedSize, descript
} }
defer file.Close() defer file.Close()
// Write the new entry // Build the SourceForge-based download URL:
// https://downloads.sourceforge.net/project/spitfire-browser/<remoteDir>/<fileName>
downloadURL := fmt.Sprintf("https://downloads.sourceforge.net/project/spitfire-browser/%s/%s", remoteDir, fileName)
// Format the entry.
entry := fmt.Sprintf(` entry := fmt.Sprintf(`
C:%s C:%s
P:%s P:%s
R:%s R:%s
V:%s V:%s
A:%s A:%s
S:%s S:%s
I:%s I:%s
T:%s T:%s
U:%s U:%s
L:%s L:%s
o:%s o:%s
m:%s m:%s
t:%d t:%d
c:%s D:%s
D:%s p:%s
p:%s q:
q: d:%s
Z:%s I:https://weforge.xyz/Spitfire/Branding/raw/branch/main/active/browser/icon.svg
S:https://spitfirebrowser.xyz/static/images/screenshots/1.png
T:browser,experimental,testing
r: Automated Nightly build of Spitfire
c:%s
`, checksum, name, release, version, arch, size, installedSize,
description, url, license, origin, maintainer, timestamp, dependencies,
platform, downloadURL, checksum)
`, checksum, name, release, version, arch, size, installedSize, description, url, license, origin, maintainer, timestamp, contentChecksum, dependencies, platform, checksum) // Trim leading newline to keep it clean
entry = strings.TrimPrefix(entry, "\n")
if _, err := file.WriteString(entry); err != nil { if _, err := file.WriteString(entry + "\n"); err != nil {
log.Fatalf("Failed to write to APPINDEX file: %v", err) log.Fatalf("Failed to write to APPINDEX file: %v", err)
} }
@ -70,7 +100,7 @@ func calcChecksum(input string) string {
return fmt.Sprintf("%x", h.Sum(nil)) return fmt.Sprintf("%x", h.Sum(nil))
} }
// removeExistingEntry removes an existing entry from APPINDEX based on P, R, A, and o fields // removeExistingEntry removes an existing entry from APPINDEX if it matches P, R, A, and o fields.
func removeExistingEntry(name, release, arch, origin string) { func removeExistingEntry(name, release, arch, origin string) {
// Read file contents // Read file contents
content, err := os.ReadFile("./APPINDEX") content, err := os.ReadFile("./APPINDEX")
@ -81,39 +111,78 @@ func removeExistingEntry(name, release, arch, origin string) {
log.Fatalf("Failed to read APPINDEX: %v", err) 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") lines := strings.Split(string(content), "\n")
var newLines []string var newLines []string
remove := false var currentEntry []string
inEntry := false // true when we're reading lines for a single entry
// Use these to store the P, R, A, o values within the current entry
var pVal, rVal, aVal, oVal string
for _, line := range lines { for _, line := range lines {
// Detect start of an entry by matching on P, R, A, and o trimmed := strings.TrimSpace(line)
if strings.HasPrefix(line, "P:"+name) {
remove = true // Detect the start of an entry (a line that starts with "C:")
} if strings.HasPrefix(trimmed, "C:") {
if remove && strings.HasPrefix(line, "R:"+release) { // If we were in an entry previously, check if it should be removed or kept
remove = true if inEntry && len(currentEntry) > 0 {
} // Decide whether to keep the previous entry
if remove && strings.HasPrefix(line, "A:"+arch) { if !(pVal == name && rVal == release && aVal == arch && oVal == origin) {
remove = true newLines = append(newLines, currentEntry...)
} newLines = append(newLines, "") // Blank line to separate entries
if remove && strings.HasPrefix(line, "o:"+origin) { }
remove = true }
// Start a new entry
currentEntry = []string{trimmed}
inEntry = true
// Reset these values for the new entry
pVal, rVal, aVal, oVal = "", "", "", ""
continue
} }
// Stop removal at the end of an entry if inEntry {
if remove && line == "" { // Collect lines for this entry
remove = false currentEntry = append(currentEntry, trimmed)
continue // Skip the line
}
// Append lines that are not part of the matching entry // Extract P, R, A, o for matching later
if !remove { switch {
newLines = append(newLines, line) case strings.HasPrefix(trimmed, "P:"):
pVal = strings.TrimPrefix(trimmed, "P:")
case strings.HasPrefix(trimmed, "R:"):
rVal = strings.TrimPrefix(trimmed, "R:")
case strings.HasPrefix(trimmed, "A:"):
aVal = strings.TrimPrefix(trimmed, "A:")
case strings.HasPrefix(trimmed, "o:"):
oVal = strings.TrimPrefix(trimmed, "o:")
}
} else {
// Lines outside of entries just get appended directly
// (e.g. if there's extraneous text before the first "C:" or after the last)
if trimmed != "" {
newLines = append(newLines, trimmed)
}
} }
} }
// Write the updated contents back to the file // Handle the last entry if we ended inEntry
err = os.WriteFile("./APPINDEX", []byte(strings.Join(newLines, "\n")), 0644) if inEntry && len(currentEntry) > 0 {
// Decide whether to keep the final entry
if !(pVal == name && rVal == release && aVal == arch && oVal == origin) {
newLines = append(newLines, currentEntry...)
}
}
// Join everything back and ensure at least one trailing newline
finalContent := strings.Join(newLines, "\n")
if !strings.HasSuffix(finalContent, "\n") {
finalContent += "\n"
}
err = os.WriteFile("./APPINDEX", []byte(finalContent), 0644)
if err != nil { if err != nil {
log.Fatalf("Failed to update APPINDEX: %v", err) log.Fatalf("Failed to update APPINDEX: %v", err)
} }