Various cleanup bits, always use the version from lsb_release instead of hardcoding

ubuntu/plucky
Simon Quigley 1 week ago
parent 4d6176bc13
commit fa0302e5aa

@ -1,12 +1,17 @@
cmake_minimum_required(VERSION 3.5.0)
project(snapd-installation-monitor)
# Enable CMake features
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
# Find required Qt6 components
find_package(Qt6 COMPONENTS Widgets DBus REQUIRED)
# Set C++ standard
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Add the main application executable
add_executable(snapd-installation-monitor main.cpp)
target_link_libraries(snapd-installation-monitor Qt6::Widgets Qt6::DBus)

@ -10,11 +10,11 @@ import (
)
// cleanUpFiles removes partial, old, and orphaned snap and assertion files from the download and assertions directories.
func cleanUpFiles(snapsDir, assertionsDir, seedYaml string) {
func cleanUpFiles(snapsDir string, assertionsDir string) {
verboseLog("Starting cleanup process...")
// Load the seed.yaml data
seedData := loadSeedData(seedYaml)
seedData := loadSeedData()
// Create a map of valid snap and assertion files based on seed.yaml
validSnaps := make(map[string]bool)

@ -12,15 +12,6 @@ import (
"github.com/snapcore/snapd/store"
)
// Seed structure for seed.yaml
type seed struct {
Snaps []struct {
Name string `yaml:"name"`
Channel string `yaml:"channel"`
File string `yaml:"file"`
} `yaml:"snaps"`
}
var (
ctx = context.Background()
storeClient *store.Store
@ -30,6 +21,7 @@ var (
processedSnaps = make(map[string]bool)
snapSizeMap = make(map[string]float64)
totalSnapSize float64
seedYaml string
)
type SnapInfo struct {
@ -61,14 +53,14 @@ func main() {
// Define directories based on the seed directory
snapsDir := filepath.Join(seedDirectory, "snaps")
assertionsDir := filepath.Join(seedDirectory, "assertions")
seedYaml := filepath.Join(seedDirectory, "seed.yaml")
seedYaml = filepath.Join(seedDirectory, "seed.yaml")
// Setup directories and seed.yaml
initializeDirectories(snapsDir, assertionsDir)
initializeSeedYaml(seedYaml)
initializeSeedYaml()
// Load existing snaps from seed.yaml
existingSnapsInYaml := loadExistingSnaps(seedYaml)
existingSnapsInYaml := loadExistingSnaps()
// Populate currentSnaps based on existing snaps
for snapName := range existingSnapsInYaml {
@ -133,7 +125,7 @@ func main() {
cleanUpCurrentSnaps(assertionsDir, snapsDir)
// Update seed.yaml with the current required snaps
if err := updateSeedYaml(snapsDir, seedYaml, currentSnaps); err != nil {
if err := updateSeedYaml(snapsDir, currentSnaps); err != nil {
log.Fatalf("Failed to update seed.yaml: %v", err)
}
@ -143,7 +135,7 @@ func main() {
if err := validateSeed(seedYaml); err != nil {
log.Fatalf("Seed validation failed: %v", err)
}
cleanUpFiles(snapsDir, assertionsDir, seedYaml)
cleanUpFiles(snapsDir, assertionsDir)
// Mark "Finalizing" as complete
if progressTracker != nil {
@ -155,11 +147,21 @@ func main() {
func collectSnapsToProcess(snapsDir, assertionsDir string) ([]SnapDetails, error) {
var snapsToProcess []SnapDetails
versionID, err := getVersionID()
if err != nil {
return nil, err
}
defaultChannel := "latest/stable/ubuntu-" + versionID
if err != nil {
return nil, err
}
fallbackChannel := "latest/stable"
for snapEntry := range requiredSnaps {
// Extract channel if specified, default to "stable"
parts := strings.SplitN(snapEntry, "=", 2)
channel := "latest/stable/ubuntu-25.04"
channel := defaultChannel
if len(parts) == 2 {
channel = parts[1]
}
@ -173,9 +175,10 @@ func collectSnapsToProcess(snapsDir, assertionsDir string) ([]SnapDetails, error
// Append only those snaps that need updates
for _, snapDetails := range snapList {
verboseLog("Processing snap: %s with result: %v", snapDetails.InstanceName, snapDetails.Result)
verboseLog("Processing snap: %s", snapDetails.InstanceName)
if len(snapDetails.Result.Deltas) > 0 {
for _, delta := range snapDetails.Result.Deltas {
verboseLog("Delta found for %s from %d to %d", snapDetails.InstanceName, delta.FromRevision, delta.ToRevision)
snapSize := float64(delta.Size)
snapSizeMap[snapDetails.Result.Info.SuggestedName] = snapSize
totalSnapSize += snapSize

@ -32,6 +32,7 @@ func collectSnapDependencies(snapName, channel, fallbackChannel, snapsDir, asser
var result *store.SnapActionResult
var err error
workingChannel := ""
// Fetch or refresh snap information
if oldSnap == nil || oldSnap.SnapID == "" || oldSnap.Revision.N == 0 {
@ -41,18 +42,25 @@ func collectSnapDependencies(snapName, channel, fallbackChannel, snapsDir, asser
result, err = fetchOrRefreshSnapInfo(snapName, nil, fallbackChannel)
if err != nil {
return nil, err
} else {
workingChannel = fallbackChannel
}
} else {
return nil, err
}
} else {
workingChannel = channel
}
} else {
verboseLog("Old snap info: %s %d", oldSnap.SnapID, oldSnap.Revision.N)
result, err = fetchOrRefreshSnapInfo(snapName, oldSnap, channel)
if err != nil {
if strings.Contains(err.Error(), "snap has no updates available") {
result, err = fetchOrRefreshSnapInfo(snapName, nil, channel)
if err != nil {
return nil, err
} else {
workingChannel = channel
}
} else if strings.Contains(err.Error(), "no snap revision available as specified") {
result, err = fetchOrRefreshSnapInfo(snapName, oldSnap, fallbackChannel)
@ -61,14 +69,20 @@ func collectSnapDependencies(snapName, channel, fallbackChannel, snapsDir, asser
result, err = fetchOrRefreshSnapInfo(snapName, nil, fallbackChannel)
if err != nil {
return nil, err
} else {
workingChannel = fallbackChannel
}
} else {
return nil, err
}
} else {
workingChannel = fallbackChannel
}
} else {
return nil, err
}
} else {
workingChannel = channel
}
}
@ -78,9 +92,10 @@ func collectSnapDependencies(snapName, channel, fallbackChannel, snapsDir, asser
info := result.Info
newSnap := &store.CurrentSnap{
InstanceName: snapName,
SnapID: info.SnapID,
Revision: snap.Revision{N: info.Revision.N},
InstanceName: snapName,
SnapID: info.SnapID,
Revision: snap.Revision{N: info.Revision.N},
TrackingChannel: workingChannel,
}
snapInCurrentSnaps, oldRevision := isSnapInCurrentSnaps(snapName)
if snapInCurrentSnaps {
@ -176,7 +191,7 @@ func fetchOrRefreshSnapInfo(snapName string, currentSnap *store.CurrentSnap, cha
results, _, err := storeClient.SnapAction(ctx, includeSnap, actions, nil, nil, nil)
if err != nil {
verboseLog("SnapAction error for %s: %v", snapName, err)
if strings.Contains(err.Error(), "snap has no updates available") && currentSnap != nil {
if (strings.Contains(err.Error(), "snap has no updates available") || strings.Contains(err.Error(), "no snap revision available as specified")) && currentSnap != nil {
return nil, err
}
return nil, fmt.Errorf("snap action failed for %s: %w", snapName, err)
@ -232,6 +247,12 @@ func findPreviousSnap(downloadDir, assertionsDir, snapName string) (string, *sto
assertFilePath := filepath.Join(assertionsDir, strings.Replace(file.Name(), ".snap", ".assert", 1))
currentSnap = parseSnapInfo(assertFilePath, snapName)
currentSnap.Revision.N = revision
trackingChannel, err := getChannelName(snapName)
if err != nil {
verboseLog("Failed to get existing channel name for %s", snapName)
continue
}
currentSnap.TrackingChannel = "latest/" + trackingChannel
}
}
}

@ -5,13 +5,42 @@ import (
"io/ioutil"
"log"
"os"
"strings"
"gopkg.in/yaml.v3"
"github.com/snapcore/snapd/store"
)
type seed struct {
Snaps []struct {
Name string `yaml:"name"`
Channel string `yaml:"channel"`
File string `yaml:"file"`
} `yaml:"snaps"`
}
// getChannelName returns the channel name for a specific snap name
func getChannelName(snapName string) (string, error) {
file, err := ioutil.ReadFile(seedYaml)
if err != nil {
return "", fmt.Errorf("failed to read seed.yaml: %w", err)
}
var seedData seed
if err := yaml.Unmarshal(file, &seedData); err != nil {
return "", fmt.Errorf("failed to parse seed.yaml: %w", err)
}
for _, snap := range seedData.Snaps {
if snap.Name == snapName {
return snap.Channel, nil
}
}
return "", fmt.Errorf("snap %s not found in seed.yaml", snapName)
}
// initializeSeedYaml ensures that seed.yaml exists; if not, creates it.
func initializeSeedYaml(seedYaml string) {
func initializeSeedYaml() {
if _, err := os.Stat(seedYaml); os.IsNotExist(err) {
file, err := os.Create(seedYaml)
if err != nil {
@ -23,7 +52,7 @@ func initializeSeedYaml(seedYaml string) {
}
// loadSeedData loads seed data from seed.yaml
func loadSeedData(seedYaml string) seed {
func loadSeedData() seed {
file, err := ioutil.ReadFile(seedYaml)
if err != nil {
log.Fatalf("Failed to read seed.yaml: %v", err)
@ -38,7 +67,7 @@ func loadSeedData(seedYaml string) seed {
}
// loadExistingSnaps loads snaps from seed.yaml into a map
func loadExistingSnaps(seedYaml string) map[string]bool {
func loadExistingSnaps() map[string]bool {
file, err := ioutil.ReadFile(seedYaml)
if err != nil {
log.Fatalf("Failed to read seed.yaml: %v", err)
@ -58,7 +87,7 @@ func loadExistingSnaps(seedYaml string) map[string]bool {
}
// updateSeedYaml updates the seed.yaml file with the current required snaps
func updateSeedYaml(snapsDir, seedYaml string, currentSnaps []*store.CurrentSnap) error {
func updateSeedYaml(snapsDir string, currentSnaps []*store.CurrentSnap) error {
// Log the snaps to be written
verboseLog("CurrentSnaps to be written to seed.yaml:")
for _, snapInfo := range currentSnaps {
@ -92,7 +121,7 @@ func updateSeedYaml(snapsDir, seedYaml string, currentSnaps []*store.CurrentSnap
File string `yaml:"file"`
}{
Name: snapInfo.InstanceName,
Channel: "stable", // Assuming 'stable' channel; modify as needed
Channel: strings.Replace(snapInfo.TrackingChannel, "latest/", "", -1),
File: snapFileName,
}
seedData.Snaps = append(seedData.Snaps, snapData)

@ -148,3 +148,28 @@ func verifySnapIntegrity(filePath, expectedChecksum string) bool {
}
return checksumMatches
}
// Get the raw VERSION_ID from /etc/os-release to use for branch detection
func getVersionID() (string, error) {
file, err := os.Open("/etc/os-release")
if err != nil {
return "", fmt.Errorf("failed to open /etc/os-release: %w", err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "VERSION_ID=") {
// Remove the prefix and any surrounding quotes
versionID := strings.Trim(strings.SplitN(line, "=", 2)[1], `"`)
return versionID, nil
}
}
if err := scanner.Err(); err != nil {
return "", fmt.Errorf("error reading /etc/os-release: %w", err)
}
return "", fmt.Errorf("VERSION_ID not found in /etc/os-release")
}

Loading…
Cancel
Save