You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
6.4 KiB
165 lines
6.4 KiB
// Copyright (C) 2024 Simon Quigley <tsimonq2@ubuntu.com>
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 3
|
|
// of the License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/snapcore/snapd/store"
|
|
)
|
|
|
|
// cleanUpFiles removes partial, old, and orphaned snap and assertion files from the download and assertions directories.
|
|
func cleanUpFiles(snapsDir string, assertionsDir string) {
|
|
verboseLog("Starting cleanup process...")
|
|
|
|
// Load the seed.yaml data
|
|
seedData := loadSeedData()
|
|
|
|
// Create a map of valid snap and assertion files based on seed.yaml
|
|
validSnaps := make(map[string]bool)
|
|
validAssertions := make(map[string]bool)
|
|
|
|
// Populate valid snaps and assertions from the seed.yaml data
|
|
for _, snap := range seedData.Snaps {
|
|
// Ensure correct extraction of revision
|
|
revision := extractRevisionFromFile(snap.File)
|
|
if revision == "" {
|
|
verboseLog("Failed to extract revision from file name: %s", snap.File)
|
|
continue
|
|
}
|
|
snapFileName := fmt.Sprintf("%s_%s.snap", snap.Name, revision)
|
|
assertionFileName := fmt.Sprintf("%s_%s.assert", snap.Name, revision)
|
|
|
|
validSnaps[snapFileName] = true
|
|
validAssertions[assertionFileName] = true
|
|
}
|
|
|
|
// Log valid snaps and assertions
|
|
verboseLog("Valid Snaps: %v", validSnaps)
|
|
verboseLog("Valid Assertions: %v", validAssertions)
|
|
|
|
// Remove outdated or partial snap files
|
|
files, err := os.ReadDir(snapsDir)
|
|
if err != nil {
|
|
verboseLog("Error reading snaps directory for cleanup: %v", err)
|
|
} else {
|
|
for _, file := range files {
|
|
filePath := filepath.Join(snapsDir, file.Name())
|
|
if strings.HasSuffix(file.Name(), ".partial") || strings.HasSuffix(file.Name(), ".delta") {
|
|
verboseLog("Removing partial/delta file: %s\n", filePath)
|
|
if err := os.Remove(filePath); err != nil {
|
|
verboseLog("Failed to remove file %s: %v", filePath, err)
|
|
} else if verbose {
|
|
verboseLog("Removed partial/delta file: %s", filePath)
|
|
}
|
|
} else if strings.HasSuffix(file.Name(), ".snap") {
|
|
if !validSnaps[file.Name()] {
|
|
verboseLog("Removing outdated or orphaned snap file: %s\n", filePath)
|
|
if err := os.Remove(filePath); err != nil {
|
|
verboseLog("Failed to remove snap file %s: %v", filePath, err)
|
|
} else if verbose {
|
|
verboseLog("Removed snap file: %s", filePath)
|
|
}
|
|
} else {
|
|
verboseLog("Snap file %s is valid and retained.\n", file.Name())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remove orphaned assertion files
|
|
files, err = os.ReadDir(assertionsDir)
|
|
if err != nil {
|
|
verboseLog("Error reading assertions directory for cleanup: %v", err)
|
|
} else {
|
|
for _, file := range files {
|
|
filePath := filepath.Join(assertionsDir, file.Name())
|
|
if strings.HasSuffix(file.Name(), ".assert") {
|
|
if !validAssertions[file.Name()] {
|
|
verboseLog("Removing orphaned assertion file: %s\n", filePath)
|
|
if err := os.Remove(filePath); err != nil {
|
|
verboseLog("Failed to remove assertion file %s: %v", filePath, err)
|
|
} else if verbose {
|
|
verboseLog("Removed assertion file: %s", filePath)
|
|
}
|
|
} else {
|
|
verboseLog("Assertion file %s is valid and retained.\n", file.Name())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
verboseLog("Cleanup process completed.")
|
|
}
|
|
|
|
// removeOrphanedFiles deletes the assertion and snap file corresponding to the removed snap.
|
|
func removeOrphanedFiles(snapName string, revision int, assertionsDir string, snapsDir string) {
|
|
assertionFilePath := filepath.Join(assertionsDir, fmt.Sprintf("%s_%d.assert", snapName, revision))
|
|
snapFilePath := filepath.Join(snapsDir, fmt.Sprintf("%s_%d.snap", snapName, revision))
|
|
if fileExists(assertionFilePath) {
|
|
err := os.Remove(assertionFilePath)
|
|
if err != nil {
|
|
verboseLog("Failed to remove assertion file %s: %v", assertionFilePath, err)
|
|
} else {
|
|
verboseLog("Removed assertion file: %s", assertionFilePath)
|
|
}
|
|
} else {
|
|
verboseLog("Assertion file %s does not exist. No action taken.", assertionFilePath)
|
|
}
|
|
if fileExists(snapFilePath) {
|
|
err := os.Remove(snapFilePath)
|
|
if err != nil {
|
|
verboseLog("Failed to remove snap file %s: %v", snapFilePath, err)
|
|
} else {
|
|
verboseLog("Removed snap file: %s", snapFilePath)
|
|
}
|
|
} else {
|
|
verboseLog("Snap file %s does not exist. No action taken.", snapFilePath)
|
|
}
|
|
}
|
|
|
|
// cleanUpCurrentSnaps removes snaps from currentSnaps that are not marked as required.
|
|
func cleanUpCurrentSnaps(assertionsDir string, snapsDir string) {
|
|
var filteredSnaps []*store.CurrentSnap
|
|
|
|
for _, snap := range currentSnaps {
|
|
if requiredSnaps[snap.InstanceName] {
|
|
filteredSnaps = append(filteredSnaps, snap)
|
|
} else {
|
|
verboseLog("Removing unnecessary snap: %s\n", snap.InstanceName)
|
|
removeOrphanedFiles(snap.InstanceName, snap.Revision.N, assertionsDir, snapsDir)
|
|
}
|
|
}
|
|
currentSnaps = filteredSnaps
|
|
|
|
// Log the updated currentSnaps
|
|
verboseLog("Filtered currentSnaps after cleanup:")
|
|
for _, snap := range currentSnaps {
|
|
verboseLog("- %s_%d.snap", snap.InstanceName, snap.Revision.N)
|
|
}
|
|
}
|
|
|
|
// removeStateJson removes the state.json file if it exists
|
|
func removeStateJson(stateJsonPath string) {
|
|
if _, err := os.Stat(stateJsonPath); err == nil {
|
|
if err := os.Remove(stateJsonPath); err != nil {
|
|
verboseLog("Failed to remove state.json: %v", err)
|
|
} else if verbose {
|
|
verboseLog("Removed state.json at %s", stateJsonPath)
|
|
}
|
|
}
|
|
}
|